Codeabbey -- dice and weighted sum

Oforth examples. Feel free to post your own code.

Codeabbey -- dice and weighted sum

Postby sotolf » 22 Aug 2015 14:23

I did some quick codeabbey again, and the first one was so simple I didn't feel that it needs a post for itself, so I decided to group it together with a much more interesting weighted sum of digits

dice

input are here some random floats between 0 and 1, and one has to make dice numbers 1-6 out of them
Code: Select all
6 Constant new: sides
: getLn { System.Console askln }                    // ( <stdin> -- string )
: getNumber { getLn asInteger }                     // ( <stdin> -- integer )
: pprint { apply(#.) printcr }                      // ( [a] -- <stdout> )
: getInput { [] getNumber #[ getLn + ] times }      // ( <stdin> -- [string] )
: number->dice { sides * floor 1 + }                // ( float -- int(1-6) )

getInput map( #[ asFloat number->dice ] ) pprint


Pretty standard stuff, and not very interesting really

Weighted sum

This one is a lot more interesting, we get in a list of numbers, and have to make a weighted sum of the digits of each one. eg. 21 = 2*1 + 1*2 = 6

Code: Select all
48 Constant new: ASCII0
: getLn { System.Console askln }                    // ( <stdin> -- string )
: getNumber { getLn asInteger }                     // ( <stdin> -- integer )
: pprint { apply(#.) printcr }                      // ( [a] -- <stdout> )
: getInput { [] getNumber getLn words }      // ( <stdin> -- [string] )
: getDigits { map( #[ asInteger ASCII0 - ])}        // ( String -- [integer] )
: ws { dup size seq zip map( #[ reduce(#*)]) sum }  // ( [integer] -- weighted-sum )

getInput map( #[ getDigits ws]) pprint


I don't really know a better way to get out the digits of a number string, but this works.
I really like how concise ws turned out just that the map reduce looks a bit ugly with all the parenthesis, brackets and hashes :P
sotolf
 
Posts: 55
Joined: 30 Jul 2015 15:53

Re: Codeabbey -- dice and weighted sum

Postby Franck » 22 Aug 2015 21:40

Hi,

1) To get a digit from a char, you can use #asDigit

Code: Select all
: getDigits { map(#asDigit)}        // ( String -- [integer] )


or, without parenthesis :

Code: Select all
: getDigits { #asDigit swap map }   // ( String -- [integer] )



2) To calculate product of a collection, #prod is already defined (like #sum) :

Code: Select all
: ws { dup size seq zip map(#prod) sum }      // ( [integer] -- weighted-sum )


or, with a local variable and without parenthesis :

Code: Select all
: ws(l) { #prod l dup size seq zip map sum }      // ( [integer] -- weighted-sum )


or, without local variable and without parenthesis :

Code: Select all
: ws { #prod swap dup size seq zip map sum }     // ( [integer] -- weighted-sum )


Here, I would opt for the first one. For the 2 last, I think #prod is too far from #map to understand quickly that it is map's parameter.

You can also use #zipWith :
Code: Select all
: ws { dup size seq zipWith(#*) sum }      // ( [integer] -- weighted-sum )


Or directly calculate the weighted sum of the string :

Code: Select all
: ws { dup size seq swap zipWith(#[ asDigit * ]) sum }    // ( aString -- n )


Many ways ... :)

Franck
Franck
 
Posts: 148
Joined: 29 Oct 2014 19:01

Re: Codeabbey -- dice and weighted sum

Postby sotolf » 24 Aug 2015 12:31

Thank you! That helps a lot, I really like the zipWith version, that's clean, and still not so hard to understand :)
sotolf
 
Posts: 55
Joined: 30 Jul 2015 15:53

Re: Codeabbey -- dice and weighted sum

Postby Franck » 24 Aug 2015 16:47

Yes, I agree, the zipWith version is cleaner. And faster because you don't need to create an intermediary map.

btw, #zip is written using #zipWith :

Code: Select all
Indexable method: zip { #[ [ , ] ] self zipWith }
Franck
 
Posts: 148
Joined: 29 Oct 2014 19:01


Return to Oforth examples

Who is online

Users browsing this forum: No registered users and 1 guest

cron