http://www.perlmonks.org?node_id=32782

I was assigned a simple program to write in C++: Make a program that takes an integer and tells whether each digit is odd or even. So, I started messing around in Perl, rather than doing the assignment (naturally). This is the shortest solution I came up with. Any suggestions for improvement? (66 chars)
chop($_=<>);s/([13579])/$1: odd\n/g;s/([02468])/$1: even\n/g;print

Replies are listed 'Best First'.
RE: shortest
by Jeff Connelly (Acolyte) on Sep 17, 2000 at 06:36 UTC
    31 characters: perl -ne's/./$&&1?o:e/eg;print'
      perl -ne's/$&&1?o:e/eg;print'

      Okay this rocks and I've voted for your code... I think this is what's happening :

      1. perl -ne ''executes the one liner forever.
        1. the regexp substitutes each character using s/./ and /g.
        2. $& is the previous matches.
        3. &1 is evaluated in the trinary operator ? using /e.
        4. if &1 then replace with odd else replace with even
      2. print defaults to $_, the results of the regular expression.
      but what I really wanna know is: what is &1?

      Brother Frankus.

        &1 is the logical and applying the bit mask (1). Even numbers always end with a zero bit, odd always end with a 1 bit. This is a simple test for even/odd.
RE: shortest
by turnstep (Parson) on Sep 17, 2000 at 07:31 UTC
    In keeping with the spirit (and format) of the original question:
    s/./print"$&: ".($&%2?odd:even)."\n"/eg;
RE: shortest
by myocom (Deacon) on Sep 16, 2000 at 08:59 UTC

    At one character less, you could do:

    chop($_=<>);for(split('',$_)){print$_.': '.($_%2?"Odd\n":"Even\n")}
RE: shortest
by indigo (Scribe) on Sep 19, 2000 at 03:28 UTC
    Also in spirit. 30 chars.
    map{print($_&1?odd:even)}/./g;
RE: shortest
by Adam (Vicar) on Sep 16, 2000 at 21:41 UTC
    chop($_=<>);$a=chop()=>print qq'\n$a: ',$a&1?'odd':'even' while $_;
    The code that was previously here has been replaced. It didn't work.

      Perhaps it's me, but this doesn't seem to produce the expected results... It reports 'odd' for every digit except '1'.

        Yup. Actually Its worse then that. Try using a number with a zero in it. It stops at the zero. I guess I should have run it instead of just trusting that it would work. (I'll try to re-write it to make it work, and I'll post the current, bad, version here so that other's will understand the mistake.)
        chop($_=<>);print "\n$a: ",$a>>1?'odd':'even' while $a=chop; # The above snipit does not work. # When I posted it, I was thinking that the bit shift >> # would return the bit shifted off the end, but of course, # sanity eventualy prevailed and I realized that it does # not do that. (duh!) # Additionally, it has a bug in that it stops on the first # zero in the number. # # TEST TEST TEST!!!