Advanced Code Golf - Disk Operations, and File Allocation

8

1

Good Afternoon Golfgeneers.

This is reasonably long and detailed question. Given what it was asking, it needed to be. If you have any questions, please ask them. If there is anything that isn't clear, please alert me to it so I can fix it. This is probably on the tougher side of codegolf.

We are building a lightweight computer, and we need the lightest weight file system possible. The shortest code will be chosen.

We are providing a cutting edge 65536 byte hard drive. For the sake of this prototype, it will be a direct image file, which your program can assume exists, and is in whichever location suits you - ie, a binary file representing the entire hard disk. You may assume that this image is already 'formatted' - ie. if your program relies on something being in the file to work, it can be. If you require the initial empty state to be something other then all-zeros, please state what it is.

There is no memory limit as to RAM used by your application.

The input and output commands will require an interface to the actual hard drive. Like the disk image, your program can assume that the file for input exists, and is wherever you want it to be. Likewise, your program can output wherever is convenient. It must however close the file after executing the input or output command.

You are not being provided with a format which you must use for the disc image - you are free to develop your own. It must be capable of storing up to 248 files. Any file greater then 256 bytes can count as a new file for the sake of this limit for every 256 bytes or part thereof. A file can be up to 63488 bytes. Basically - it must be as capable as a hard drive with 248 sectors of 256 bytes each.

The reasoning behind these seemingly sizes is to give you 2048 bytes of 'administration' - to store details of the files. Each file/folder must be accessible by a name of 4 alphanumeric characters, which may be case sensitive or insensitive as per your preference. If your program supports names of 4 or less characters, then there is bonus of a 0.95 multiplier.

Your program must accept, via stdin, the following commands. Parameters will be separated by a space. The command will be terminated by a newline.

  • L - List the names to stdout of all the current files and their sizes in bytes, separated by newlines.
  • C a b - Copy file a to new file b.
  • D a - Delete file a
  • R a b - Renames file a to new name b
  • I a - Adds the input file (see note above) as file a
  • O a - Outputs file a to the output file

The following errors may be reported to STDOUT or STDERR as valid reasons for a command to fail to execute. You may choose to only print ERR# where # is the number of the error:

  • 1 - File doesn't exist
  • 2 - File already exists
  • 3 - Out of space*

* Note that your program can not issue this just because it is out of continuous space. If you still have sectors available, you must defragment the disk to make it work.

A folder system is optional - however, will net a bonus of a 0.8 multiplier to your score. If it supports more then 1 level of directory, it will net a bonus of a 0.7 multiplier (not in addition to the 0.8). For the bonus, you must have

  • L, R, C and D only work within the current directory. L must list folders in the current directory, as well as the files.
  • New command M a b moves file a to folder b. If b is '.', moves file to the parent director
  • New command G a goes to folder a. If a is '.', goes to parent folder
  • R must also rename folders
  • D must also delete folders, and any files/folders within them
  • C must also copy folders, and any files/folders within them

The following additional errors may be reported to STDOUT or STDERR as valid reasons for a command to fail to execute.

  • 4 - Folder doesn't exist
  • 5 - File, not folder required - where, I and O require file names, and a folder was given

Your score is:

  • The size, in bytes, of your source code
  • Multiplied by

    • 0.95 if you support names of 4, or less characters
    • 0.8 if you support a single level of folders
    • 0.7 if you support multiple levels of folders
    • 0.95 if you support commands (not necessarily file names) in lower or uppercase

Good luck.

lochok

Posted 2013-04-05T07:01:12.300

Reputation: 3 139

I am willing to make allowances for languages which do not support something required by this challenge. Unfortunately, I don't think I can make it work just via command line parameters for GolfScript. – lochok – 2013-04-05T07:07:41.183

2Looks complex enough to need a good test suite. – Peter Taylor – 2013-04-05T07:40:25.623

I'll start working on one - but may not be done today – lochok – 2013-04-05T07:41:33.847

Are the score multipliers compounded? – jdstankosky – 2013-04-05T13:34:59.163

Compounded. Note that you can only get one of the single level or multiple levels of folders though. – lochok – 2013-04-05T22:29:20.887

Answers

3

Ruby, score 505.4 (560 characters)

x,a,b=gets.chomp.split
f=IO.read('F')
e=f[0,4*X=248].unpack 'A4'*X
s=f[4*X,2*X].unpack 's'*X
d=f[6*X..-1].unpack 'A'+s*'A'
u,v,w,y=[[N=nil,q=e.index(a),!t=e.index(""),"e[t]=a;s[t]=(d[t]=IO.binread('I')).size"],[!q,r=e.index(b),!t,"e[t]=b;d[t]=d[q];s[t]=s[q]"],[!q,N,N,"e[q]=d[q]='';s[q]=0"],[!q,r,N,"e[q]=b"],[!q,N,N,"IO.binwrite('O',d[q])"],[N,N,N,'X.times{|i|e[i]>""&&puts(e[i]+" #{s[i]}")}']]['ICDROL'=~/#{x}/i]
u&&$><<"ERR1\n"||v&&$><<"ERR2\n"||w&&$><<"ERR3\n"||eval(y)
d=d*""
d.size>63488&&$><<"ERR3\n"||IO.write('F',(e+s+[d]).pack('A4'*X+'s'*X+'A63488'))

Notes:

  • Filesystem is located in file F in the current directory. F must exist and may be created/formatted via the following command: IO.write('F',(([""]*248)+([0]*248)+[""]).pack('A4'*248+'s'*248+'A63488')).
  • Input file is always I also in the current directoy, output file is O.
  • Since it wasn't required to check errors, be sure to type correct commands (i.e. no unsupported commands, no missing arguments, too long filenames).
  • The file system implementation is extremely simple - for each command the full hard drive is read into memory and rebuild upon (successful) completion.

Bonuses:

  • Filenames may be 1-4 chars
  • Commands may be upper or lower case

The code is not yet fully golfed but shows already that for a substancial better score I'd try a completely different approach.

Test session (only STDIN/STDOUT is shown but of course each command is prepended by calling the above program):

> L
> I F001
> L
F001 558
> I F001
ERR2
> C F002 F003
ERR1
> C F001 F003
> L
F001 558
F003 558
> C F001 F003
ERR2
> R F002 F003
ERR1
> R F001 F003
ERR2
> R F001 F002
> L
F002 558
F003 558
> O F001
ERR1
> O F002
> L
F002 558
F003 558
> D F001
ERR1
> D F002
> L
F003 558
> C F003 F001
> L
F001 558
F003 558
> D F001
> L
F003 558
> D F003
> L

Howard

Posted 2013-04-05T07:01:12.300

Reputation: 23 109

3

Tcl, score 487,711 (772 bytes)

{*}[set a {interp alias {}}] s {} dict se f
{*}$a u {} dict un f
{*}$a h {} dict g
proc 0 {} {return -level 1}
proc p {n a b} {foreach l $n {proc $l $a "global f c;$b;S"}}
p L\ l {} {puts [join [dict k [h $f {*}$c]] \n]}
p C\ c a\ b {s {*}$c $b [h $f {*}$c $b]}
p D\ d a {u {*}$c $a}
p R\ r a\ b {s {*}$c $a [h $f {*}$c $b];u {*}$c $b}
p I\ i a {set i [open i rb];s {*}$c $a [read $i];close $i}
p O\ o a {set o [open o wb];chan puts $o [h $f {*}$c $a];close $o}
p M\ m a\ b {set d $c;if {$b eq "."} {set d [lrange $c 0 end-1]};s {*}$d $a [h $f {*}$c $a];u {*}$c $a}
p G\ g a {if {$a eq "."} {set c [lrange $c 0 end-1]} {lappend c $a}}
p S {} {puts [set o [open F wb]] $f;close $o;return}
set f [read [set i [open F rb]]]
close $i
set c {}
while 1 {{*}[split [gets stdin]]}

Bonuses (gotta catch them all):

  • support file names with 4 byte or less - or more. I don't care. 0.95
  • support multilevel folders 0.7
  • support lower and upper case commands 0.95

Known limitations:

  • File system F must already exist. Empty or whitespace is fine.
  • I don't check the size of the file system - I don't care.
  • Input file is i, outputfile is o and the filesystem is in F
  • Errors will crash the program.
  • No checks if file/directory exist, might be an error.
  • No difference between a file and a directory. Yes, you can write a directory to output and use this as file system.
  • Using a file as directory that is not a valid file system will result in an error.
  • No input validation. Invalid commands may throw an error. Or not: eval puts [expr 1+2]
  • No command to create a directory (was not my idea), but will be created implicit by I (also not my idea, and G doesn't create)
  • G does not validate the directory.
  • Filenames could contain spaces, but the interface does not support them.
  • Concurrent modification of the same file system is not supported.

Some hacks:

  • eval puts $c -> current directory, separated by spaces.
  • exit - no comment.
  • lappend c . -> switches into the subdirectory .

Johannes Kuhn

Posted 2013-04-05T07:01:12.300

Reputation: 7 122

3

Python 2.7 373 (413 bytes)

from pickle import*
E=exit;o=open;D,I,W='DIw'
def T(i):w[i]in d and E('ERR2')
d=load(o(D))
w=raw_input().split();b=w[0].upper()
if b=='L':
 for k in d:print k,len(d[k])
elif b==I:T(1);d[w[1]]=o(I).read()
else:
 a=w[1];a in d or E('ERR1')
 if b in'RC':T(2);d[w[2]]=(b<D and d.get or d.pop)(a)
 if b==D:d.pop(a)
 if b=='O':o(I,W).write(d[a])
d=dumps(d,-1)
x=65536-len(d)
x>-1or E('ERR3')
o(D,W).write(d+I*x)

The disk is saved in the Python pickle-Format: to create an empty disk you have to put these two bytes '}.' at the beginning and optionally 65534 fill bytes afterwards. Supports arbitrary large filenames (*0.95), upper and lowercase commands (*0.95) and hard links (:-).

Daniel

Posted 2013-04-05T07:01:12.300

Reputation: 1 801