perlmeditation
tadman
[Odud]'s recent posting on [id://87639] came with a little
puzzle to do with giving change, which is simple enough,
and is certainly golf material.
Suppose you are trying to write a function <I>c</I> that,
give the amount you want, and an array reference to the
units of currency that you have available in order from
lowest to highest, will return a list of the required
change.
<BR>
<BR>
For instance, if $22.50 was specified, along with a US
currency specification, assuming no $2 bills are available
in the area:
<CODE> print join(',',c(22.50,[.01,.05,.1,.25,1,5,10,20,50,100]));
</CODE>
Would output:
<CODE> 20,1,1,0.25,0.25
</CODE>
Of course, other countries use different units, such as:
<CODE> print join(',',c(22.50,[.01,.05,.1,.20,1,2,5,10,20,50,100]));
</CODE>
Which would show:
<CODE> 20,2,0.2,0.2,0.1
</CODE>
Amounts less than the smallest unit of currency are not
handled, so they can be ignored.
<BR>
<BR>
Here's my baseline, which is 115 characters, not including
linebreaks required for presentation:
<CODE>sub c{
($t,$p,@r)=@_;@p=map{int($_*100)}@$p;
$t=int($t*100);while($v=pop@p and$t>0
){while($t>=$v){push@r,$v/100;$t-=$v;
}}@r
}
</CODE>
You will note the use of integer math only. I am perplexed
by the floating point math. As [Obdud] says, this exercise
should teach "simple arithmetic, looping, lists, sorting,
etc." where 'etc.' apparently refers to floating point
idiosyncrasies, such as the following:
<CODE> print "$t != $v\n" if ($t != $v);
</CODE>
Which surprisingly shows:
<CODE> 0.1 != 0.1
</CODE>
Where the values were actually: $t = 0.099999999999999977795540,
$v = 0.100000000000000005551115, due to some minor floating
point issues in the 17th decimal place.