How can this code be improved?

Add a reply

Posted by alia 253 days ago:
The following code, when optimized, gets to 360 bytes, and I just can't think of any other ways to reduce the file size. I have no ideas how the people who did this in PHP in 132 bytes managed to do it. Here's the code uncompressed:

<?
list($h,$m)=explode(':',fgets(STDIN));
$h=(int)$h;
$m=floor(((int)$m)/5);
for($x=0;$x<12;$x++)
{
$c[$x]='o';
}
if($h>=12)
$h=$h-12;
if($h==$m)
{$c[$h]='x';}
else
{
$c[$h]='h';$c[$m]='m';
}

$o=<<<EOT
$c[0]
$c[11] $c[1]

$c[10] $c[2]

$c[9] $c[3]

$c[8] $c[4]

$c[7] $c[5]
$c[6]
EOT;
echo $o;

---------

Here it is compressed:
<?list($h,$m)=explode(':',fgets(STDIN)); $h=(int)$h; $m=floor(((int)$m)/5); for($x=0;$x<12;$x++){$c[$x]='o';} if($h>=12)$h=$h-12; if($h==$m){$c[$h]='x';} else{$c[$h]='h';$c[$m]='m';} $o=<<<EOT
$c[0]
$c[11] $c[1]

$c[10] $c[2]

$c[9] $c[3]

$c[8] $c[4]

$c[7] $c[5]
$c[6]
EOT;
echo $o;

Any pointers at all on what i can do to reduce file size will be very much appreciated.
Posted by eyepopslikeamosquito 253 days ago:
I've made some quick and obvious shortenings below to get you started.

<?
$r=fgets(STDIN);
$h=+$r;
$m=+substr($r,3)/5|0;
for($x=0;$x<12;$x++)$c[$x]='o';
$h%=12;
if($h==$m)
{$c[$h]='x';}
else
{
$c[$h]='h';$c[$m]='m';
}
printf('%9s
%5s%8s

%2s%14s

%s%16s

%2s%14s

%5s%8s
%9s',$c[0],$c[11],$c[1],$c[10],$c[2],$c[9],$c[3],$c[8],$c[4],$c[7],$c[5],$c[6]);

Though many more shortenings are possible I don't want to spoil your fun. HTH.
Posted by alia 252 days ago:
wow, thanks!!!
Posted by alia 252 days ago:
can you explain the following two lines, or point to the relavant link on php manual?

$h=+$r;
$m=+substr($r,3)/5|0;
Posted by eyepopslikeamosquito 252 days ago:
First note that while I'm an experienced golfer, I'm a PHP novice; I've never written a non-golf PHP program in my life. The main tactic I use in PHP golf is "Can't possibly work; let's try it anyway". You quite often discover surprising and undocumented features that way.

Now to your specific questions:

$h=+$r;

PHP -- like Perl, but unlike Python and Ruby -- allows you to use strings in numeric expressions without explicit conversion. I originally wrote that as:

$h=0+$r

but then applying the rule "can't possibly work, try it anyway", I tried removing the leading zero and it worked. It seems you can give the PHP parser a hint that you want to use a string in numeric context by using a leading "+". For example, if ("abc") evaluates to true, while if (+"abc") evaluates to false because in numeric context "abc" is zero. I found this out simply by experimenting with tiny PHP programs. Here's a weird one: "1E1"%6 evaluates to 1 because "1E1" is interpreted as 1, while "1E1"*1%6 evaluates to 4 because multiplying by one causes the PHP parser to interpret "1E1" as 10 (scientific notation). This looks like a bug to me, or at least it surprised me. There are many dusty corners of PHP that are unspecified, an accident of implementation, and this looks like one of them. Yet these dusty corners are sometimes useful to golfers.

As for:

$m=+substr($r,3)/5|0;

the leading + is used to set numeric context, as before. Unfortunately, dividing by 5 produces a floating point answer when we really want integer division. To avoid the long (int) that you used I tried a number of different tricks, until I noticed a logical or | with zero produced the required integer division. There are doubtless other ways to do it. Actually, I just realised by trying it that it also works without the leading plus; that is:

$m=substr($r,3)/5|0

also works, as does:

$m=substr($r,3)/5%99

though that is one stroke longer. There may be an even shorter way to do integer division in PHP that I haven't thought of.
Posted by alia 250 days ago:
Ok, so by using
$h=+$r;

where r is something like '05:35'
you get $h = 5, with the '0' and ':35' removed. Is that correct?

That's a nice trick.

And then you're using the bitwise operator | to round the product of the minutes' division. I'll need to do some more research to understand how that works..

Thanks again for your help!
Posted by eyepopslikeamosquito 250 days ago:

Ok, so by using
$h=+$r;

where r is something like '05:35'
you get $h = 5, with the '0' and ':35' removed. Is that correct?

Yes. It is a nice PHP trick. Doesn't work in the other three languages though. Each language has its own quirks and, to be successful at golf, you need to experiment to find out what's possible. Python and Ruby both refuse to allow this without explicit conversion (by using the int() function in Python and the to_i method in Ruby). Python is the strictest of the gang of four languages in that the other three languages are all happy to terminate their string to int conversion routine when they hit the first non numeric character in the string (: in this example) ... but not Python. To illustrate:

# Python test code.
r = "05:35"
h=0+r # oops: "TypeError: unsupported operand type(s) for +: 'int' and 'str'"
h=int(r) # oops: "ValueError: invalid literal for int() with base 10: '05:35'"
h=int(r[:2]) # ... finally, this works :)



Posted by alia 250 days ago:
thanks mate :)

Add a reply