Decode the chmod

26

5

Challenge

Given a three digit octal permissions number, output the permissions that it grants.

chmod

On UNIX OSes file permissions are changed using the chmod command. There are few different ways of using chmod, but the one we will focus on today is using octal permissions.

The three digits in the permissions number represent a different person:

  • The first digit represents the permissions for the user
  • The second digit represents the permissions for the group
  • The last digit represents the permissions for others

Next, each digit represents a permission as shown below in:

Key: number | permission

7 | Read Write and Execute
6 | Read and Write
5 | Read and Execute
4 | Read only
3 | Write and Execute
2 | Write only
1 | Execute only
0 | None

Input

The input will be the three digit number as a string, e.g.:

133

or

007

This will be passed either via STDIN or via function arguments.

Output

Your output should be the different permissions for each of the user, the group and the others. You must display this information like so:

User:   ddd
Group:  ddd
Others: ddd

Where there are three spaces after User, two spaces after Group and one space after Others. You replace ddd with the permissions information.

Your output may be to STDOUT or as a returned string.

Examples

Input: 666

Output:

User:   Read and Write
Group:  Read and Write
Others: Read and Write

Input: 042

Output:

User:   None
Group:  Read only
Others: Write only

Input: 644

Output:

User:   Read and Write
Group:  Read only
Others: Read only

Winning

The shortest code in bytes wins.

Beta Decay

Posted 2016-09-13T11:12:05.270

Reputation: 21 478

What are the specifications of the input? – Jonathan Allan – 2016-09-13T11:23:01.843

@JonathanAllan Just the three digit number – Beta Decay – 2016-09-13T11:29:40.590

You mean as a decimal integer only, so 042 would be received as 42? – Jonathan Allan – 2016-09-13T11:31:50.403

2@Jonathan No, it's a string input so it'd be 042 – Beta Decay – 2016-09-13T11:50:19.720

Are we allowed to have an int-array or three ints as input? Or we need to use the String and then parse to digits? – Kevin Cruijssen – 2016-09-13T14:58:33.193

@KevinCruijssen You need to have a string and parse the digits – Beta Decay – 2016-09-13T14:59:21.457

Is using a tab instead of [3|2|1] spaces allowed? – aross – 2016-09-14T09:48:01.683

@aross No, you must use spaces since all of the answers have used spaces – Beta Decay – 2016-09-14T09:50:12.537

@BetaDecay Except the PHP one :) – aross – 2016-09-14T10:02:34.040

@aross Oh right haha – Beta Decay – 2016-09-14T10:11:14.350

The top JavaScript entry currently also uses a tab at time of writing. – Neil – 2016-09-14T10:50:17.127

1The output looks right with a tab character, so why not use it? Just to penal languages that need more bytes to pad a string? – Titus – 2016-09-14T11:32:51.113

@Titus No, because I specified to use spaces, which almost every other submission does – Beta Decay – 2016-09-16T06:09:24.473

Answers

3

05AB1E, 89 87 bytes

”‚Ý:‚Ù:ˆ†:”ð¡v”Šª0ÍÃ20‡í20‡í1ÍÃ0‚Ø20‚Ø1ÍÃ0‚Ø1‡í0‚؇í1ÍÔ2ð'€É«:1ð'€ƒ«:0ð«¡¹Nèèð3N-×ìyì,

Summons the Cthulhu encoding. Uses the CP-1252 encoding. Try it online!

Adnan

Posted 2016-09-13T11:12:05.270

Reputation: 41 965

14

Javascript (ES6), 165 161 bytes

n=>[0,1,2].map(i=>(s='User:  3Group: 68Others:58None576Read48Write476Execute475and4576only'.split(/(\d+)/))[i*2]+s[n[i]*2+1].replace(/./g,c=>' '+s[c*2])).join`
`

Edit: +1 byte to fulfill the "no tab" rule

Examples

let f =
n=>[0,1,2].map(i=>(s='User:  3Group: 68Others:58None576Read48Write476Execute475and4576only'.split(/(\d+)/))[i*2]+s[n[i]*2+1].replace(/./g,c=>' '+s[c*2])).join`
`
console.log(f("666"));
console.log(f("042"));
console.log(f("644"));
console.log(f("137"));

Arnauld

Posted 2016-09-13T11:12:05.270

Reputation: 111 334

You can gain a few bytes by rearranging the array (and maybe separating the numbers from the strings). +1 for the idea. – Titus – 2016-09-13T15:45:30.117

@Titus - I've to admit that I fail to see a rearrangement that saves some bytes. Also, the numbers have to be treated as strings so that replace() works on them without coercing. But I may be missing your point. – Arnauld – 2016-09-13T15:59:01.290

@Titus - Something like 'User3Group68Others58None576Read48Write476Execute475and4576only'.split(/(\d+)/) might work. Is that what you had in mind? – Arnauld – 2016-09-13T16:22:19.317

I was misunderstanding them; thought they were octal values. :) But your new idea is not bad either. – Titus – 2016-09-13T16:26:44.483

Challenge output requires spaces instead of tabs as it is currently written. – Mwr247 – 2016-09-14T17:26:10.923

@Mwr247 - This is apparently still under discussion, but I did the update anyway (+1 byte). – Arnauld – 2016-09-14T17:37:33.253

13

GNU sed, 187 163 158 (157+1) bytes

Run with -r (ERE regexp). File contains no trailing newline.

s/(.)(.)/User:   \1\nGroup:  \2\nOthers: /g
s/[4-7]/Read &/g
s/[2367]/Write &/g
s/[1357]/Execute &/g
s/(\w) (\w+) [1-7]/\1 and \2/g
s/[1-7]/only/g
s/0/None/g

FireFly

Posted 2016-09-13T11:12:05.270

Reputation: 7 107

Nice approach but you can save about 20 bytes by removing the digits when you add the and or only. – Neil – 2016-09-13T14:30:50.047

@Neil there :) incorporated your suggestion for a very significant save. – FireFly – 2016-09-13T14:48:28.390

1The first line could be just: s/(.)(.)/User: \1\nGroup: \2\nOthers: /. Some more bytes could be saved by porting to Perl, which has \d and \K. – ninjalj – 2016-09-16T19:06:49.247

@ninjalj good point. I'll stick to sed since I don't know Perl, and I'm sure there'd be other tricks to pull there to make it even shorter, outside of s/// replacements. – FireFly – 2016-09-18T17:27:30.620

In the 3-last substitution, you can use a word boundary and the multiline flag to save some bytes. – user41805 – 2019-12-30T20:24:17.393

6

Jelly, 100 91 85 bytes

Almost certainly golfable - 91 bytes, what?! 8 months and 6 wisdom bytes!
- 1. more string compression;
- 2. remove the post-ordinal decrement by 48 since indexing is modular;
- 3. use better tacit chaining).

-9 bytes with the kind help of @Lynn running string compressions for me

,“£ɱ~»
Ñ
ṖK,“ and”,Ṫ
LĿK
7RBUT€Uị“ØJƓ“¥Ị£“¤/¡»Ç€“¡*g»ṭ
“ṖŒhJ"ỵd¡»ḲðJ4_⁶ẋ⁸,"j€”:ż⁹Oị¢¤Y

Test it at TryItOnline

How?

,“£ɱ~» - Link 1: pair with the string "Only"

Ñ - Link 2: call next link

ṖK,“ and”,Ṫ - Link 3: insert " and" between the last two elements of x
Ṗ           - x[:-1]
 K          - join with spaces
   “ and”   - the string " and"
          Ṫ - x[-1]
  ,      ,  - pair

LĿK - Link 4: call appropriate link and add missing spaces
L   - length
 Ŀ  - call link at that index
  K - join the result with spaces

7RBUT€Uị“ØJƓ“¥Ị£“¤/¡»Ç€“¡*g»ṭ - Link 5: construct all 8 cases
7R                            - range of 7: [1,2,3,4,5,6,7]
  B                           - binary (vectorises): [[1],[1,0],[1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
   U                          - reverse (vectorises): [[1],[0,1],[1,1],[0,0,1],[1,0,1],[0,1,1],[1,1,1]]
    T€                        - indexes of truthy values for each: [[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
      U                       - reverse (vectorises): [[1],[2],[2,1],[3],[3, 1],[3,2],[3,2,1]]
        “ØJƓ“¥Ị£“¤/¡»         - list of strings: ["Execute","Write","Read"]
       ị                      - item at index (vectorises): [["Execute"],["Write"],["Write","Execute"],["Read"],["Read","Execute",["Read","Write"],["Read","Write","Execute"]]
                     ǀ       - call the previous link for each
                       “¡*g»  - the string "None"
                            ṭ - tack (Jelly is 1-based so the 8th item will be indexed as 0)

“ṖŒhJ"ỵd¡»ḲðJṚ⁶ẋ⁸,"j€”:ż⁹Oị¢¤Y - Main Link: parse input and make the result. e.g.: "042"
“ṖŒhJ"ỵd¡»                     - dictionary compression of "User Group Others"
          Ḳ                    - split at spaces -> ["User","Group","Others"]
           ð                   - dyadic chain separation, call that g (input as right)
            J                  - range of length of g -> [1,2,3]
             Ṛ                 - reverse -> [3,2,1]
              ⁶                - literal space
               ẋ               - repeat -> ["   ","  "," "]
                ⁸              - chain's left argument, g
                  "            - zip with:
                 ,             -   pair -> [["User","   "],["Group","  "],["Others"," "]]
                     ”:        - literal ':'
                   j€          - join for €ach -> ["User:   ","Group:  ","Others: "]
                            ¤  - nilad followed by link(s) as a nilad:
                        ⁹      - chain's right argument, the input string -> "042"
                         O     -   cast to ordinal (vectorises) -> [48, 52, 50]
                           ¢   -   call last link (5) as a nilad  -> ["Execute Only","Write Only","Write and Execute","Read Only","Read and Execute","Read and Write","Read Write and Execute","None"]
                          ị    -   index into (1-based & modular) -> ["None","Read Only","Write Only"]
                       ż       - zip together -> [["User:   ","None"],["Group:  ","Read Only"],["Others: ","Write Only"]]
                             Y - join with line feeds -> ["User:   ","None",'\n',"Group:  ","Read Only",'\n',"Others: ","Write Only"]
                               - implicit print:
                                             >>>User:   None
                                             >>>Group:  Read Only
                                             >>>Others: Write Only

Jonathan Allan

Posted 2016-09-13T11:12:05.270

Reputation: 67 804

6

C# 214 Bytes

string h(string y){string e="Execute ",r="Read ",w="Write ",O="Only",a="and ";var z=new[]{"None",e+O,w+O,w+a+e,r+O,r+a+e,r+a+w,r+w+a+e};return$"User:   {z[y[0]-'0']}\nGroup:  {z[y[1]-'0']}\nOthers: {z[y[2]-'0']}";}

pinkfloydx33

Posted 2016-09-13T11:12:05.270

Reputation: 308

4

Octave, 185 bytes

@(n)fprintf('User:   %s\nGroup:  %s\nOthers: %s',{'Read Write and Execute','Read and Write','Read and Execute','Read only','Write and Execute','Write only','Execute only','None'}{56-n})

Create anonymous function that takes the input as a string: '042'. Convert it to an array: (56-'042)' = [0 4 2]. Use this as multiple cell indices to index the cell array with Read Write and Execute','Read and Write', .... Uses fprintf to output the three strings, with the appropriate categories: User:, Group: and Others:.

I tried finding a way to store Execute, Write, Read as separate words and concatenate as needed, but this turned out longer than the naive approach.

Examples:

1> f('000')
User:   None
Group:  None
Others: None
2> f('042')
User:   None
Group:  Read only
Others: Write only

Try it online.

Stewie Griffin

Posted 2016-09-13T11:12:05.270

Reputation: 43 471

2You can save a few bytes using strsplit('Read Write and Execute*Read and Write*Read and Execute*Read only*Write and Execute*Write only*Execute only*None','*') instead of the cell array literal – Luis Mendo – 2016-09-13T15:35:27.263

4

PowerShell v2+, 189 168 bytes

[char[]]$args[0]|%{('User','Group','Others')[$i++]+":`t"+('None','Read','Write','Execute','only','and')[(0,(3,4),(2,4),(2,5,3),(1,4),(1,5,3),(1,5,2),(1,2,5,3))[$_-48]]}

Loops through the input $args[0] as a char-array. Each iteration, we index into an array with $i++ (defaults to 0) to select User, Group, or Others, concatenate that with a colon and a tab, and concatenate that with another array index.

Here's the magic. We implicitly cast the char to an int and subtract 48 (i.e., turning ASCII 48 ("0") into 0), choosing the appropriate wording as an array of ints. That array is subsequently used as the index into the 'None','Read','Write','Execute','only','and' array. Since the default $ofs (Output Field Separator) is a space, this correctly inserts spaces between the array elements when stringified (which happens when it concatenates to the left).

These three strings are left on the pipeline, and output via implicit Write-Output happens at program completion.

Example

PS C:\Tools\Scripts\golfing> .\decode-the-chmod.ps1 '123'
User:   Execute only
Group:  Write only
Others: Write and Execute

AdmBorkBork

Posted 2016-09-13T11:12:05.270

Reputation: 41 581

3

Straw, 193 bytes

((01234567)((None)(Execute only)(Write only)(Write and Execute)(Read only)(Read and Execute)(Read and Write)(Read Write and Execute)))::~<:{-¢(User:   ),+>
>}:{-¢(Group:  ),+>
>}-¢(Others: ),+>

Try it online

Push 3 times a conversion table on the first stack, switch to the second stack, convert each number using the conversation table and print.

TuxCrafting

Posted 2016-09-13T11:12:05.270

Reputation: 4 547

2

PHP, 169 159 bytes

foreach([User,Group,Others]as$i=>$u){echo"
$u: ";for($n=[5,33,34,66,35,67,131,531][$i]];$n;$n>>=3)echo["and",Execute,Write,Read,only,None][$n&7]," ";}

takes string as command line argument: php -r '<code>' <argument>,
prints a leading newline instead of a trailing one

Thanks to Jörg for pointing out my bugs - and for the \t.

PHP, 169 bytes

with the new restriction: (tab character forbidden)

foreach(['User:  ','Group: ','Others:']as$i=>$u){echo"
$u";for($n=[5,33,34,66,35,67,131,531][$argv[1][$i]];$n;$n>>=3)echo' ',['and',Read,Write,Execute,only,None][$n&7];}

This is 1 byte shorter than with str_pad, because of the additional blank it would require.

breakdown

foreach([User,Group,Others]as$i=>$u)
{
    echo"\n$u:\t";                      // print newline, who, blanks
    for($n=[5,33,34,66,35,67,131,531]   // octal values for words indexes
        [$argv[1][$i]]                  // (last word=highest digit)
        ;$n;$n>>=3)                     // while value has bits left
        echo['and',Execute,Write,Read,only,None][$n&7]," "; // print that word
}

To create the array for $n, use this:

$b=[[5],[1,4],[2,4],[2,0,1],[3,4],[3,0,1],[3,0,2],[3,2,0,1]];
foreach($b as$i=>$a){for($v=$j=0;$a;$j+=3)$v+=array_shift($a)<<$j;echo"$v,";}

Titus

Posted 2016-09-13T11:12:05.270

Reputation: 13 814

1foreach(['User','Group','Others']as$i=>$u){echo"\n$u:\t"; saves some bytes and the output for 3,4,6 is wrong – Jörg Hülsermann – 2016-09-13T16:17:46.473

1This is the right order [5,33,34,66,35,67,131,531] nice idea – Jörg Hülsermann – 2016-09-13T16:29:25.667

I have forget 'User' to User for exmple saves the next 6 Bytes you want to beat JavaScript do it – Jörg Hülsermann – 2016-09-13T16:38:54.043

@JörgHülsermann: I was about to adopt the "\t" anyway; thanks. +1 for that :) Good eye on the 33! – Titus – 2016-09-13T16:50:29.947

1for 346 our output is User: Read and Write Group: Execute only Others: Write and Execute it should User: Write and Execute Group: Read Only Others: Read and Write – Jörg Hülsermann – 2016-09-13T17:11:23.347

@JörgHülsermann: Fixed. These are the correct values: [5,33,34,66,35,67,131,531] – Titus – 2016-09-13T17:42:12.587

How exactly are you supposed to pass the argument? Your golfed version seems to be incorrect – aross – 2016-09-14T09:59:55.780

No using of tabs either – aross – 2016-09-14T10:03:03.870

Dear downvoter: why? – Titus – 2016-09-23T15:23:31.743

2

Haskell, 186 Bytes

s=zip(words"7654 6 7632 753 7531 0 421")(words"Read and Write and Execute None only")
m c=mapM_(\(x,y)->putStrLn(x++unwords[b|(a,b)<-s,elem y a]))$zip["User:   ","Group:  ","Others: "]c

Example:

Prelude> :r
[1 of 1] Compiling Main             ( decCh.hs, interpreted )
Ok, modules loaded: Main.
*Main> m "654"
User:   Read and Write
Group:  Read and Execute
Others: Read only

Only Prelude used. Am I doing this right?

Ungolfed:

s = zip (words "7654 6 7632 753 7531 0 421")
        (words "Read and Write and Execute None only")

ps y = unwords [b|(a,b)<-s,elem y a] -- build permissions string
pp (x,y) = putStrLn $ x ++ ps y -- print user + permission

m c =   let up = zip ["User:   ","Group:  ","Others: "] c -- pair user and permission
        in mapM_ pp up --print each

michi7x7

Posted 2016-09-13T11:12:05.270

Reputation: 405

2

Python 2, 190 185 bytes

def f(i):
 r,w,a,x,o,g="Read ","Write ","and ","Execute ","only",["User:  ","Group: ","Others:"];p=["None",x+o,w+o,w+a+x,r+o,r+a+x,r+a+w,r+w+a+x]
 for z in 0,1,2:print g[z],p[int(i[z])]

Leaves a trailing space if Execute or Write are at the end of the line but I didn't see that this wasn't allowed.

EDIT Saved 5 bytes by changing range(3) to 0,1,2 and checking byte count on my Linux laptop instead of my Windows one (\n = \r\n or the other way round. I can never remember which).

ElPedro

Posted 2016-09-13T11:12:05.270

Reputation: 5 301

2

Python 2, 240 239 238 237 228 bytes

I thought I’d finally give this cold golf thing a go. Hopefully trailing whitespace is allowed. (fixed, and in the process saved a byte)

i=0
def a(b):
 for d in 4,2,1:
    if b&d:yield('Execute','Write','Read')[d/2]
for k in raw_input():
 b,q=list(a(int(k))),' and';e=len(b)
 if e:b[~e/2]+=(' only',q,q)[e-1]
 print'UGOsrteohrue:pr :s  :'[i::3],' '.join(b)or None;i+=1

Jack Greenhill

Posted 2016-09-13T11:12:05.270

Reputation: 121

Welcome to PPCG, and nice first answer! – ETHproductions – 2016-09-14T16:17:13.080

I have shamelessly replaced the range(3) in my Python 2 answer to 0,1,2 after reading through your code. Nice answer. +1 – ElPedro – 2016-09-14T21:08:41.780

2

bash - 221 213 bytes

GNU bash, version 4.3.46

l=("User:   " "Group:  " "Others: ")
o=\ only;a=" and ";x=Execute;w=Write;r=Read
b=(None "$x$o" "$w$o" "$w$a$x" "$r$o" "$r$a$x" "$r$a$w" "$r $w$a$x")
for c in `echo $1|grep -o .`;{ echo "${l[$((z++))]}${b[$c]}";}

Unclear if this can be condensed any further, at least not without fundamentally changing the approach here (splitting up input and using it as an index to the array ${b} that holds the corresponding strings).

frames

Posted 2016-09-13T11:12:05.270

Reputation: 41

1It's shorter with \ only expanded inline. grep -o .<<<$1 is shorter than echo $1|grep -o ., but reading the input from stdin with while read -n1 c is better. Array indexes have arithmethic context in bash, so ${l[z++]} works. l would be shorter as a string, which would be accessed as ${l:z++*8:8} (offset and length have arithmethic context). Another byte can be sh?aved by reading the whole mode in c, expanding "User: ", ... inline and making judicious use of parameter expansions. – ninjalj – 2016-09-20T23:13:36.807

1For an end result of: a=" and ";x=Execute;w=Write;r=Read;b=(None $x\ only $w\ only "$w$a$x" $r\ only "$r$a$x" "$r$a$w" "$r $w$a$x");read c;echo "User: ${b[${c%??}]}\nGroup: ${b[${c:1:1}]}\nOthers: ${b[${c:2}]}" (replace \n with literal newlines). – ninjalj – 2016-09-20T23:14:52.513

1

Visual Basic, 606 Bytes

imports System.Collections
module h
sub main()
Dim i As String=console.readline()
Dim s=new Stack(new String(){"Others: ","Group:  ","User:   "})
for each j as Char in i
dim t=new Stack()
if((asc(j) MOD 2)=1)then t.push("Execute")
if(asc(j)=50 or asc(j)=51 or asc(j)=54 or asc(j)=55)then t.push("Write")
if(asc(J)>51)then t.push("Read")
if t.count=3 then
w(s.pop+t.pop+" "+t.pop+" and "+t.pop)
else
if t.count=2 then
w(s.pop+t.pop+" and "+t.pop)
else
if t.count=0 then
w(s.pop+"None")
else
w(s.pop+t.pop+" only")
end if
end if
end if
next
end sub
sub w(s As String)
console.writeline(s)
end sub
end module

polyglotrealIknow

Posted 2016-09-13T11:12:05.270

Reputation: 21

1Welcome to PPCG! Nice first answer BTW :) – Beta Decay – 2017-06-03T10:11:11.347

1

Crystal, 200 194 Bytes

def m(y)y=y.chars.map &.to_i
a=" and "
o=" only"
r="Read"
w="Write"
x="Execute"
c=["None",x+o,w+o,w+a+x,r+o,r+a+x,r+a+w,r+" "+w+a+x]
"User:   "+c[y[0]]+"
Group:  "+c[y[1]]+"
Others: "+c[y[2]]end

returns the resulting string for a given octal-sequence as a string. e.g.: m("670") results to: User: Read and Write\nGroup: Read Write and Execute\nOthers: None.

Try it online.

Domii

Posted 2016-09-13T11:12:05.270

Reputation: 219

1

Javascript, 213 209 208 188 186 bytes

function(d){a=" and ";r="Read";w="Write";e="Execute";v=";";o=" only";c=["None",e+o,w+o,w+a+e,r+o,r+a+e,r+a+w,r+" "+w+a+e];return"User: "+c[d[0]]+"\nGroup: "+c[d[1]]+"\nOthers: "+c[d[2]]}

Saved 20 bytes thanks to Dada!

Paul Schmitz

Posted 2016-09-13T11:12:05.270

Reputation: 1 089

3I might be mistaken, but shouldn't your array be in the opposite order? If I call b("000"), it returns "Read Write and Execute" while one could expect "None"... – Dada – 2016-09-13T12:52:03.340

And I'm pretty sure this could be more golfed. For instance, a 191 byte version : function b(p){a=" and ";r="Read";w="Write";e="Execute";v=";";o=" only";c=["None",e+o,w+o,w+a+e,r+o,r+a+e,r+a+w,r+" "+w+a+e];return"User: "+c[p[0]]+"\nGroup: "+c[p[1]]+"\nOthers: "+c[p[2]]}. – Dada – 2016-09-13T13:02:20.667

1

Groovy, 217 207 205 bytes

def c(m){def i=0,e='Execute',w='Write',r='Read',o=' only',a=' and ';m.each{println(['User:   ','Group:  ','Others: '][i++]+['None',"$e$o","$w$o","$w$a$e","$r$o","$r$a$e","$r$a$w","$r $w$a$e"][it as int])}}

ungolfed:

def c(m) {
  def i=0,e='Execute',w='Write',r='Read',o=' only',a=' and ';
  m.each{
    println(['User:   ','Group:  ','Others: '][i++]+['None',"$e$o","$w$o","$w$a$e","$r$o","$r$a$e","$r$a$w","$r $w$a$e"][it as int])
  }
}

norganos

Posted 2016-09-13T11:12:05.270

Reputation: 51

1

Java 7, 300 284 bytes

String c(String s){char[]a=s.toCharArray();return"User:   "+f(a[0])+"Group:  "+f(a[1])+"Others: "+f(a[2]);}String f(int i){return new String[]{"None","Execute only","Write only","Write and Execute","Read only","Read and Execute","Read and Write","Read Write and Execute"}[i%48]+"\n";}

Direct approach for now. Will try to come up with a more generic approach to reuse the words.

Ungolfed & test cases:

Try it here.

class M{
  static String c(String s){
    char[] a = s.toCharArray();
    return "User:   " + f(a[0]) + "Group:  " + f(a[1]) + "Others: " + f(a[2]);
  }

  static String f(int i){
    return new String[]{ "None", "Execute only", "Write only", "Write and Execute", "Read only", "Read and Execute", "Read and Write", "Read Write and Execute" }
      [i % 48] + "\n";
  }

  public static void main(String[] a){
    System.out.println(c("666"));
    System.out.println(c("042"));
    System.out.println(c("644"));
  }
}

Output:

User:   Read and Write
Group:  Read and Write
Others: Read and Write

User:   None
Group:  Read only
Others: Write only

User:   Read and Write
Group:  Read only
Others: Read only

Kevin Cruijssen

Posted 2016-09-13T11:12:05.270

Reputation: 67 575

1

C#, 322 337 348 bytes

That's for sure not the shortest version, but I tried solving this problem using bitwise operators since the chmod values are actually bit flags. Also C# is probably not the best golfing language :D

string P(string s){Func<int,string>X=p=>{var a=new List<string>();if((p&4)>0)a.Add("Read");if((p&2)>0)a.Add("Write");if((p&1)>0)a.Add("Execute");return a.Count>1?string.Join(" ",a.Take(a.Count-1))+" and "+a.Last():a.Count>0?a.First()+" only":"none";};return string.Join("\n",(new[]{"User:   ","Group:  ","Others: "}).Select((c,i)=>c+X(s[i]-'0')));}

ungolfed: (with comments)

string P(string s)
{
    // Function that determines the permissions represented by a single digit (e.g. 4 => "Read only")
    Func<int, string> X = p => 
    {
        var a = new List<string>();         // temporary storage for set permissions
        if ((p & 4) > 0) a.Add("Read");     // Read bit set
        if ((p & 2) > 0) a.Add("Write");    // Write bit set
        if ((p & 1) > 0) a.Add("Execute");  // Execute bit set

        // actually just Output formatting ... Takes a lot of bytes *grr*
        return a.Count > 1 
            ? string.Join(" ", a.Take(a.Count - 1)) + " and " + a.Last() 
            : a.Count > 0 
                ? a.First() + " only" 
                : "none";
    };

    // Actual result:
    return string.Join("\n", (new[] { "User:   ", "Group:  ", "Others: " })
        .Select((c, i) => c + X(s[i] - '0'))); // Map "User, .." to its permissions by using above function
}

This is my first time code golfing, so please tell me, if I did anyting wrong :)

EDIT 1:

Saved some bytes by replacing s[i]-'0' by s[i]&7 (at the very end) and saving list count into variable:

string P(string s){Func<int,string>X=p=>{var a=new List<string>();if((p&4)>0)a.Add("Read");if((p&2)>0)a.Add("Write");if((p&1)>0)a.Add("Execute");var c=a.Count;return c>1?string.Join(" ",a.Take(c-1))+" and "+a.Last():c>0?a[0]+" only":"none";};return string.Join("\n",(new[]{"User:   ","Group:  ","Others: "}).Select((c,i)=>c+X(s[i]&7)));}

EDIT 2:

Changed to lambda expression:

s=>{Func<int,string>X=p=>{var a=new List<string>();if((p&4)>0)a.Add("Read");if((p&2)>0)a.Add("Write");if((p&1)>0)a.Add("Execute");var c=a.Count;return c>1?string.Join(" ",a.Take(c-1))+" and "+a.Last():c>0?a[0]+" only":"none";};return string.Join("\n",(new[]{"User:   ","Group:  ","Others: "}).Select((c,i)=>c+X(s[i]&7)));}

Stefan

Posted 2016-09-13T11:12:05.270

Reputation: 261

1

Mathematica, 211 bytes

{r,w,e,o,a}={"Read ","Write ","Execute ","only ","and "};""<>Transpose@{{"User:   ","Group:  ","Others: "},"None"[{e,o},{w,o},{w,a,e},{r,o},{r,a,e},{r,a,w},{r,w,a,e}][[#]]&/@IntegerDigits[#,10,3],"\n"&~Array~3}&

A straightforward implementation (probably easily beatable): doesn't compute anything, just hard-codes each possible output. Input is an integer; outputs each line with a trailing space, and a trailing newline overall.

IntegerDigits[#,10,3] gives the three digits of the input (even if there are leading zeros). Each digit indicates an argument of the "function"

"None"[{e,o},{w,o},{w,a,e},{r,o},{r,a,e},{r,a,w},{r,w,a,e}]

with 0 indicating the function name itself. ""<> concatenates all the strings in a list (of lists). "\n"&~Array~3 produces the three newlines.

Greg Martin

Posted 2016-09-13T11:12:05.270

Reputation: 13 940

I just noticed that my Python 2 answer is almost identical to yours, even using the same variable names. I honestly hadn't seen yours before I posted! – ElPedro – 2016-09-14T12:03:56.390

1no worries! I think the variable names' matching is pretty much to be expected in this situation :) – Greg Martin – 2016-09-14T17:59:12.243

Guess you're right. The variable names were a bit predictable ☺ – ElPedro – 2016-09-14T18:21:04.560

btw, +1 cos we think the same way :-) – ElPedro – 2016-09-14T20:06:30.033

1btw, I don't know Mathematica but I think you may be able to lose a byte by removing the space from "only ". It will always be at the end of a line so doesn't need a trailing space. – ElPedro – 2016-09-14T20:10:38.997

1

C# 307 241 210 bytes

string X(string s){var z="User: ,Group: ,Others:,5,34,14,123,04,023,021,0123,Read,Write,and,Execute,only,None".Split(',');return string.Join("\n",s.Zip(z,(a,b)=>b+z[a-45].Aggregate("",(x,y)=>x+" "+z[y-37])));}

Formatted

string X(string s)
{
    var z = "User:  ,Group: ,Others:,5,34,14,123,04,023,021,0123,Read,Write,and,Execute,only,None".Split(',');
    return string.Join("\n", s.Zip(z, (a, b) => b + z[a - 45].Aggregate("", (x, y) => x + " " + z[y - 37])));
}

Grax32

Posted 2016-09-13T11:12:05.270

Reputation: 1 282

1

Java 7, 278

Golfed:

String f(String i){String o="";for(int n=0;n<i.length();)o+=(n<1?"User:   ":n<2?"Group:  ":"Others: ")+new String[]{"None","Execute only","Write only","Write and Execute","Read only","Read and Execute","Read and Write","Read Write and Execute"}[i.charAt(n++)-48]+"\n";return o;}

Ungolfed:

  String f(String i) {
    String o = "";
    for (int n = 0; n < i.length();)
      o += (n < 1 ? "User:   " : n < 2 ? "Group:  " : "Others: ")
        + new String[] { "None", "Execute only", "Write only", "Write and Execute", "Read only", "Read and Execute",
            "Read and Write", "Read Write and Execute" }[i.charAt(n++) - 48]
        + "\n";
    return o;
  }

Output:

User:   Read and Write
Group:  Read and Write
Others: Read and Write

User:   None
Group:  Read only
Others: Write only

User:   Read and Write
Group:  Read only
Others: Read only

user18932

Posted 2016-09-13T11:12:05.270

Reputation:

1

Python 3.5, 3.6 - 235 232 228 216 bytes

(should work on all Python 3.x)

So the input is on STDIN here (saves an import ☺).

a=input()
r=range
for i in r(3):
 p=int(a[i]);x=[["Read","Write","Execute"][j]for j in r(3)if 4>>j&p]
 if x[1:]:x[-1:-1]="and",
 if len(x)==1:x+="only",
 print(["User:  ","Group: ","Others:"][i]," ".join(x)or"None")

Making use of tuples, omitting spaces where possible and operator precedence where you would normally put parentheses to make your intentions clear.

Sample usage:

$ echo -n '666' | python3 golf2.py
User:   Read and Write
Group:  Read and Write
Others: Read and Write
$ echo -n '644' | python3 golf2.py
User:   Read and Write
Group:  Read only
Others: Read only
$ echo '042' | python3 golf2.py
User:   None
Group:  Read only
Others: Write only
$ echo '123' | python3 golf2.py
User:   Execute only
Group:  Write only
Others: Write and Execute
$ echo -n '777' | python3 golf2.py
User:   Read Write and Execute
Group:  Read Write and Execute
Others: Read Write and Execute

Un-golfed:

input_perms = list(map(int, input()))

entities = ["User", "Group", "Others"]
perm_names = ["Read", "Write", "Execute"]

for i in range(3):
    bits = input_perms[i]
    perms = [
        perm_names[j]
        for j in range(3)
        if (1 << (2-j)) & bits
    ]

    if len(perms) > 1:
        perms.insert(-1, "and")
    if len(perms) == 1:
        perms.append("only")

    print("{:7} {}".format(
        entities[i]+":",
        " ".join(perms) or "None"
    ))

Jonas Schäfer

Posted 2016-09-13T11:12:05.270

Reputation: 200

1

Batch, 280 bytes

@echo off
set/pc=
call:l "User:   " %c:~0,1%
call:l "Group:  " %c:~1,1%
call:l "Others: " %c:~2,1%
exit/b
:l
for %%s in (None.0 Execute.1 Write.2 "Write and Execute.3" Read.4 "Read and Execute.5" "Read and Write.6" "Read Write and Execute.7") do if %%~xs==.%2 echo %~1%%~ns

Hardcoding the strings was 47 bytes shorter than trying to piece them together. Would have been 267 bytes if tabs were legal.

Neil

Posted 2016-09-13T11:12:05.270

Reputation: 95 035

0

C#, 371 bytes

public String[] a = {"none","Execute only","Write only","Write and Execute","Read only","Read and Execute","Read and Write","Read Write and Execute"};
public String pA(int i){return a[i];}
public int d(int n,int i){
  n=n/Math.pow(10,i);
  return n%=10;
}
public void main(int i){
  Console.Write("User:\t{0}\nGroup:\t{1},Others:\t{2}",pA(d(i,0)),pA(d(i,1)),pA(d(i,2));
}

Alireza Tabatabaeian

Posted 2016-09-13T11:12:05.270

Reputation: 101

4This is code-golf, so you must golf your code. Also, add a header with the name of the language and the bytecount. – TuxCrafting – 2016-09-13T12:07:32.607

I've added your byte count, which is your score. You need to get your score as low as possible to win – Beta Decay – 2016-09-13T12:10:09.153

For example, you get rid of all of the unnecessary whitespace in each function – Beta Decay – 2016-09-13T12:10:57.607

1@BetaDecay Thanks,I'm new to this community and I think I'd better to use php instead which could be lead to more compacts codes. – Alireza Tabatabaeian – 2016-09-13T12:13:43.097

1@Alireza That's a good idea. Although on this site, we do like to see short answers in Java and C# :) – Beta Decay – 2016-09-13T12:17:39.643

@AlirezaTabatabaeian I don't think you should just abandon a language. For a head start, remove any unnecessary spaces and newlines, and try to use \t to denote a literal tab character, i.e. \t is one byte, not two. – Erik the Outgolfer – 2016-09-13T13:19:46.573

I was going to write a C# answer, but yours is actually pretty good with a few modifications. There's quite a bit you can do with this one. You can remove the whitespace, use lambdas and use string interpolation. I was able to get it down to 291 without touching the string array. Although, and this is the problem with C# for golf, if it's a full program that's required it'll jump right back to ~400 because of the namespace and class definitions required to make it execute :/ – Brandon – 2016-09-13T13:42:23.117

0

PHP ,199 Bytes

foreach([User,Group,Others]as$i=>$u){$a=[];foreach([Read,Write,Execute]as$k=>$s)if($argv[1][$i]&4>>$k)$a[]=$s;$a[]=($x=array_pop($a))?$a?"and $x":"$x only":None;echo str_pad("\n$u:",9).join(" ",$a);}

PHP ,189 Bytes with \t

foreach([User,Group,Others]as$i=>$u){$a=[];foreach([Read,Write,Execute]as$k=>$s)if($argv[1][$i]&4>>$k)$a[]=$s;$a[]=($x=array_pop($a))?$a?"and $x":"$x only":None;echo"\n$u:\t".join(" ",$a);}

Jörg Hülsermann

Posted 2016-09-13T11:12:05.270

Reputation: 13 026

Hey, you should use spaces instead of tabs – Beta Decay – 2016-09-14T10:11:42.097

In this case \t looks like str_repeat(" ",3-$i) or str_pad("",3-$i," ") but is does not matter with my idea I have no chance to win.If I Should take another space https://www.cs.tut.fi/~jkorpela/chars/spaces.html

– Jörg Hülsermann – 2016-09-14T11:12:41.993

113+34 bytes to save. In the long version: Use echo str_pad("$u:",8) instead of echo"$u:".str_repeat(" ",3-$i) (-9); this renders $i=> obsolete (-4).

In both versions: Use $a[$z-1]="and $a[$z-1]"; instead of {$a[]=$a[$z-1];$a[$z-1]="and";} (-7) and else$a[]=$a?Only:None; instead of elseif($z<1)$a[]=None;else$a[]=Only; (-14).

Turn if(1<$z=count($a))$a[$z-1]="and $a[$z-1]";else$a[]=$a?Only:None; into if($x=array_pop($a))$a[]=$a?"and $x":"$x Only";else$a[]=None; (-3) and then into $a[]=($x=array_pop($a))?$a?"and $x":"$x Only":None; (-10) – Titus – 2016-09-14T12:29:41.070

@Titus echo str_pad("$u:",8),$a[$z-1]="and $a[$z-1]";,else$a[]=$a?Only:None; Done $i=> obsolete I can not do then $m=$argv[1][$i] is necessary. For the rest I would try first another way. Thank You for the input – Jörg Hülsermann – 2016-09-14T14:52:29.150

meta hint: check the help on comments. You can use mini-Markdown: links, italic, bold and code. – Titus – 2016-09-14T14:58:43.573

1More ideas: if(4&$m=$argv[1][$i]) instead of $m=$argv[1][$i];if(4&$m) (-3) OR replace $m=;if();if();if(); with a loop: foreach([Read,Write,Execute]as$k=>$s)if($argv[1][$i]&4>>$k)$a[]=$s; (-7) – Titus – 2016-09-14T15:16:14.177

the foreach loop is a very good idea. my version can't crack your version and maybe we can force your version – Jörg Hülsermann – 2016-09-14T16:07:34.050

The double ternary assignment can be put inside the join: join(" ",$a[]=...) (-3). Leading instead of trailing newline str_pad("\n$u:",9) could give another (-3). I think that´s all that can be done here. – Titus – 2016-09-14T16:16:32.120

0

Python 3.5 - 370 294 243 bytes

Golfed:

import sys
a=lambda o: [print(('User:  ','Group: ','Others:')[n],('None','Execute only','Write only','Write and Execute','Read only','Read and Execute','Read and Write','Read Write and Execute')[int(o[n])]) for n in range(0,3)]
a(sys.argv[1])

Size check:

$ du -b OctalToHuman.py 
243     OctalToHuman.py

Un-golfed:

#!/usr/bin/env python3
from sys import argv as ARGS

types = ('User:  ', 'Group: ', 'Others:')
perms = ('None','Execute only','Write only','Write and Execute','Read only','Read and Execute','Read and Write','Read Write and Execute')

def convert(octal_string):
    for n in range(0,3):
        print(types[n], perms[int(octal_string[n])])

if __name__ == '__main__':
    convert(ARGS[1])

Sample output:

$ python ./OctalToHuman.py 666
User:   Read and Write
Group:  Read and Write
Others: Read and Write

$ python ./OctalToHuman.py 042
User:   None
Group:  Read only
Others: Write only

$ python ./OctalToHuman.py 644
User:   Read and Write
Group:  Read only
Others: Read only

Ray

Posted 2016-09-13T11:12:05.270

Reputation: 101

This is not a serious contender for the winning criteria. We require all answers to make a serious attempt at optimizing their score for the winning criteria (for example, in code golf challenges such as this one, submissions must make a serious attempt at minimizing the byte count of the program). – Mego – 2016-09-13T19:06:23.997

You can save quite a few bytes by removing import sys, and just making the program an anonymous function (lambda o:...). – NoOneIsHere – 2016-09-18T17:31:32.923

0

Sinclair BASIC - 263 257 bytes

I did one version using the same approach as everyone else (load of string variables put into array) in 227 bytes, so going to post this one as a different way of doing it.

EDIT - As pointed out, there were some extraneous "and" appearing, this is now resolved

1 p=0,z$="and ": INPUT c$
2 FOR EACH a$ IN ["User:   ","Group:  ","Others: "]
3 p+=1,n=VAL c$(p),r=(n & 4)>0,w=(n & 2)>0,x=(n & 1)>0,t=r+w+x
4  ?a$;("Read "*r)+(z$*(r AND (t=2)))+("Write "*w)+(z$*(w AND x))+("Execute "*x)+("only"*(t=1))+("None"*(t=0))
5 NEXT a$

Uses bitwise-AND & operation to see if the number has 4,2 or 1 bits set and then prints the different permissions. Adding "and" in between multiple values took up most of the space.

Screenshot shows example for 670 as input

enter image description here

Brian

Posted 2016-09-13T11:12:05.270

Reputation: 1 209

Does not follow the spec. Your second line should say Read Write and Execute. This answer should be non- competing. – Shaun Wild – 2016-09-15T14:38:33.547

I love Sinclair BASIC. Which interpreter do you use? – Beta Decay – 2016-09-18T17:29:28.507

Not sure if someone changed the language name, it's actually SpecBAS which is a more modern version of the original Sinclair BASIC – Brian – 2016-09-19T10:19:59.037

0

F#, 204 203 Bytes

my first golf, so do please forgive any mistakes ;)
The golfed version (based 1:1 on pinkfloydx33's answer):

fun(y:string)->let e,r,w,o,a="Execute ","Read ","Write ","only","and ";let z=["None";e+o;w+o;w+a+e;r+o;r+a+e;r+a+w;r+w+a+e;];let(!-)a=z.[int y.[a]-48];sprintf"User:   %s\nGroup:  %s\nOthers: %s"!-0!-1!-2

The ungolfed version:

fun (y : string) ->
    let e, r, w, o, a = "Execute ", "Read ", "Write ", "only", "and "
    let z = [
                "None";
                e + o;
                w + o;
                w + a + e;
                r + o;
                r + a + e;
                r + a + w;
                r + w + a + e;
            ]
    let (!-) a = z.[int(y.[a]) - 48]
    sprintf "User:   %s\nGroup:  %s\nOthers: %s" !-0 !-1 !-2

Example usage:

let k =  ...... // function definition goes here

printf"%s"<|k"755"
printf"%s"<|k"042"
// etc ...


This is solely to check, whether I could 'improve' pinkfloydx33's answer - I do not take any credit for the algorithm

unknown6656

Posted 2016-09-13T11:12:05.270

Reputation: 101

0

Python 3, 191 bytes

def d(n):a,b,c,d,e=' and ',' only',"Execute","Write","Read";l=["None",c+b,d+b,d+a+c,e+b,e+a+c,e+a+d,e+" "+d+a+c];y,u,i=map(int,n);return"User:   %s\nGroup:  %s\nOthers: %s\n"%(l[y],l[u],l[i])

ungolfed

def d(n):
    a,b,c,d,e=' and ',' only',"Execute","Write","Read"
    l=["None",c+b,d+b,d+a+c,e+b,e+a+c,e+a+d,e+" "+d+a+c]
    y,u,i=map(int,n)
    return"User:   %s\nGroup:  %s\nOthers: %s\n"%(l[y],l[u],l[i])

Aleksandr Smirnov

Posted 2016-09-13T11:12:05.270

Reputation: 1

1Welcome to PPCG! nice first post! – Rɪᴋᴇʀ – 2016-09-15T01:34:51.697

Hmm, I'm very curious how moderator got 151bytes when I only get 191 :D Is it mistake? Check edits – Aleksandr Smirnov – 2016-09-15T09:11:07.650

That was me, sorry. I typo'ed in the edit. Fixed now. – Rɪᴋᴇʀ – 2016-09-15T14:13:21.740

0

Javascript (ES6), 159 bytes

a=>`User:  ${(b=[' None',(c=' Execute')+(d=' only'),(e=' Write')+d,f=e+(g=' and')+c,(h=' Read')+d,h+g+c,h+g+e,h+f])[a[0]]}\nGroup: ${b[a[1]]}\nOthers:`+b[a[2]]

Example:

(a=>`User:  ${(b=[' None',(c=' Execute')+(d=' only'),(e=' Write')+d,f=e+(g=' and')+c,(h=' Read')+d,h+g+c,h+g+e,h+f])[a[0]]}\nGroup: ${b[a[1]]}\nOthers:`+b[a[2]])("042")

Ian

Posted 2016-09-13T11:12:05.270

Reputation: 1

0

Perl -p, 149 (148+1) bytes

This is a port to Perl of Firefly's sed answer.

s/(.)(.)/User:   \1                                                             
Group:  \2
Others: /;s/[4-7]/Read $&/g;s/[2367]/Write $&/g;s/[1357]/Execute $&/g;s/0/None/g;s/\w \K(\w+) \d/and $1/g;s/\d/only/g

Compared to sed:

  • Perl uses $& instead of & (+ 3 bytes).
  • Perl has \d, which we use instead of [1-7] (-6 bytes).
  • Perl has \K (-3 bytes).
  • Perl allows literal newlines in the replacement part of s/// (-2 bytes).

ninjalj

Posted 2016-09-13T11:12:05.270

Reputation: 3 018