Page 1 of 2
FizzBuzz
Posted: Sun 18 Nov 2012, 05:32
by GustavoYz
I surprised myself reading
this.
Is likely a very easy challenge, but effective somehow.
Im wondering if there is a bash solution (one line, not a script) shorter than this mess I just did
:
Code: Select all
for nn in `seq 1 100`; do { [ $(( $nn % 15 )) == 0 ] && echo "FizzBuzz"; } || { [ $(( $nn % 5 )) == 0 ] && echo "Buzz"; } || { [ $(( $nn % 3 )) == 0 ] && echo "Fizz"; } || ( echo "$nn") ; done | column
Although is like "cheat" on this context, my Perl solution end up being (way) shorter:
Code: Select all
perl -E 'say $_ % 15 ? $_ % 3 ? $_ % 5 ? "$_" : "Buzz" : "Fizz" : "Fizzbuzz" for 1 .. 100 ' | column
(note that both commands are piped to `column` for easy reading, not essential).
As I know that there is a lot of Bash wisdom surrounding, I'm wondering, are there better/shorter(/prettier) Bash ways?
Re: FizzBuzz
Posted: Sun 18 Nov 2012, 09:04
by jamesbond
GustavoYz wrote:Im wondering if there is a bash solution (one line, not a script) shorter than this mess I just did
:
Code: Select all
for nn in `seq 1 100`; do { [ $(( $nn % 15 )) == 0 ] && echo "FizzBuzz"; } || { [ $(( $nn % 5 )) == 0 ] && echo "Buzz"; } || { [ $(( $nn % 3 )) == 0 ] && echo "Fizz"; } || ( echo "$nn") ; done | column
That's just "sh" not "bash". This is bash:
Code: Select all
for ((a=1; a <= 100; a++)); do ! ((a%15)) && echo FizzBuzz || ! ((a%3)) && echo Fizz || ! ((a%5)) && echo Buzz || echo $a; done | column
I'm sure technosaurus can make it even shorter
Re: FizzBuzz
Posted: Sun 18 Nov 2012, 19:00
by GustavoYz
jamesbond wrote:GustavoYz wrote:Im wondering if there is a bash solution (one line, not a script) shorter than this mess I just did
:
Code: Select all
for nn in `seq 1 100`; do { [ $(( $nn % 15 )) == 0 ] && echo "FizzBuzz"; } || { [ $(( $nn % 5 )) == 0 ] && echo "Buzz"; } || { [ $(( $nn % 3 )) == 0 ] && echo "Fizz"; } || ( echo "$nn") ; done | column
That's just "sh" not "bash". This is bash:
Code: Select all
for ((a=1; a <= 100; a++)); do ! ((a%15)) && echo FizzBuzz || ! ((a%3)) && echo Fizz || ! ((a%5)) && echo Buzz || echo $a; done | column
And that's incorrect...
I appreciate the reply, but your "Bash" way is grouping the || and && in the wrong way and you have more than 100 items on that...
Posted: Sun 18 Nov 2012, 19:39
by rcrsn51
Is the objective to have the least amount of code or the least amount of computation?
Posted: Sun 18 Nov 2012, 20:04
by GustavoYz
rcrsn51 wrote:Is the objective to have the least amount of code or the least amount of computation?
I would like to learn a "better" way of achieve the same on the shell (trough Bash or sh) if is possible.
If two versions of the same command, working equally well and at comparable speed, i'd prefer the shorter and/or mnemonic.
Re: FizzBuzz
Posted: Sun 18 Nov 2012, 22:51
by jamesbond
GustavoYz wrote:
And that's incorrect...
That was an optimisation went wrong. My original version looked like this before I tried to over-optimise and remove the "continue" with || ...
Code: Select all
time for ((a=1; a <= 100; a++)); do ! ((a%15)) && echo FizzBuzz && continue; ! ((a%3)) && echo Fizz && continue; ! ((a%5)) && echo Buzz && continue; echo $a; done
Re: FizzBuzz
Posted: Mon 19 Nov 2012, 18:09
by GustavoYz
jamesbond wrote:Code: Select all
time for ((a=1; a <= 100; a++)); do ! ((a%15)) && echo FizzBuzz && continue; ! ((a%3)) && echo Fizz && continue; ! ((a%5)) && echo Buzz && continue; echo $a; done
Thanks!
FizzBuzz
Posted: Wed 21 Nov 2012, 16:03
by L18L
Before this thread is SOLVED another FizzBuzz
not fast
not short
but
python
Code: Select all
for a in range(1,101):
if a % 15 == 0:
print 'FizzBuzz'
continue
if a % 5 == 0:
print 'Fizz'
continue
if a % 3 == 0:
print 'Buzz'
continue
print a
or 2 lines less but slower:
Code: Select all
for a in range(1,101):
if a % 15 == 0:
print 'FizzBuzz'
elif a % 5 == 0:
print 'Fizz'
elif a % 3 == 0:
print 'Buzz'
else:
print a
or:
Code: Select all
for a in range(1,101):
p = ''
if not a % 5 : p += 'Fizz'
if not a % 3 : p += 'Buzz'
if not p : p = a
print p
Why learn bash if....
Posted: Wed 21 Nov 2012, 18:16
by GustavoYz
Well, I wasn't after a python script or solution and my question was about 'one-liners', but thanks a lot anyway.
I solved it on python time ago (using the interpreter originally) with this code:
Code: Select all
python -c 'print ["Fizz"[i%3*4:]+"Buzz"[i%5*4:]or str(i)for i in range(1,101)]'
but found plenty python versions that taught me better ways...
Why learn bash if....
Lots of reasons... Quick one? There is not such thing as a python shell yet, to replace actual Bash/sh/zsh or even tclsh.
Buy Python is great, no discussions on that (I've to deal with it everyday
)
I am (still) curious about how much less code is possible to solve the task in the shell (Bash or Sh).
FizzBuzz
Posted: Wed 21 Nov 2012, 19:09
by L18L
GustavoYz wrote:I am (still) curious about how much less code is possible to solve the task in the shell (Bash or Sh).
not less but fast:
a one liner in my console wrote:# time i=0;while [ $i -lt 100 ];do i=$(($i+1));p='';[[ $((i%3)) -eq 0 ]] && p='Fizz';[[ $((i%5)) -eq 0 ]] && p="${p}Buzz";[ "$p" ]|| p=$i;echo -n "$p ";done
real 0m0.000s
user 0m0.000s
sys 0m0.000s
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz #
Posted: Thu 22 Nov 2012, 01:54
by GustavoYz
Thanks.
Posted: Mon 26 Nov 2012, 07:18
by technosaurus
that was about what I had too
Code: Select all
n=0;s="";b="";while [ $((n)) != 100 ]; do b="";n=$(($n+1));[ $(($n%3)) == 0 ] && b=Fizz;[ $(($n%5)) == 0 ] && b=${b}Buzz"
";[ "$b" ] && s=$s" "$b || s=$s" "$n;done;echo "$s"
prints out 5 tab separated columns using only basic shell
Note it is normally much faster to echo $s (without formatting) than "$s" (with formatting)
or some variation of
Code: Select all
n=0;s="";while [ $(($n)) != 100 ];do n=$(($n+1));case $(($n%15)) in 3|6|9|12)s=$s" "Fizz;;5|10)s=$s" "Buzz"
";;0)s=$s" "FizzBuzz"
";;*)s=$s" "$n;;esac;done;echo "$s"
creating the string only takes ~ 0.01s on my box while outputting it to the console takes ~0.05 ... output to a file reduces this to ~0.002s though
with bashisms it could be simplified to
Code: Select all
n=0;s="";while [ $((n++)) != 100 ];do case $(($n%15)) in 3|6|9|12)s=$s" "Fizz;;5|10)s=$s" "Buzz"
";;0)s=$s" "FizzBuzz"
";;*)s=$s" "$n;;esac;done;echo "$s"
Posted: Mon 26 Nov 2012, 11:49
by linuph
technosaurus:
that's 0.03 user seconds on my P3 1GHz with echo to console, 0.02 with echo to file
Posted: Mon 26 Nov 2012, 13:37
by technosaurus
here is the C for comparison
Code: Select all
#include <stdio>
int void main(){
int n=0;
while (n++ < 100){
switch (n%15){
case 3 :
case 6 :
case 9 :
case 12 :
printf("Fizz\t");
break;
case 5 :
case 10 :
printf("Buzz\n");
break;
case 0 :
printf("FizzBuzz\n");
break;
default :
printf("%d\t",n);
}
}
}
Posted: Mon 26 Nov 2012, 16:22
by rcrsn51
Very nice. Doing three divisions is clearly overkill. Doing one division is better.
Posted: Mon 26 Nov 2012, 17:27
by technosaurus
rcrsn51 wrote:
Very nice. Doing three divisions is clearly overkill. Doing one division is better.
Its not exactly a duff's device, but that is what I was recalling as a template.
Posted: Mon 26 Nov 2012, 17:39
by GustavoYz
@technosaurus: Nice, thanks.
Posted: Tue 27 Nov 2012, 08:30
by jamesbond
rcrsn51 wrote:Very nice. Doing three divisions is clearly overkill. Doing one division is better.
I have one that does not use division at all; but surprisingly it is slower
Code: Select all
for ((a=1,b=2,c=4;a<101;a++,b--,c--));do d=$a;((\!b && \!c))&&d=FizzBuzz b=3 c=5;((\!b))&&d=Fizz b=3;((\!c))&&d=Buzz c=5;echo $d; done
Posted: Tue 27 Nov 2012, 16:12
by rcrsn51
jamesbond wrote:I have one that does not use division at all; but surprisingly it is slower
Is this an example of "loop unwinding"? Where the amount of processing needed to manage the loop is more than what's required to execute the contents of the loop?
So maybe three divisions is not a bad thing if it reduces the total amount of processing.
Posted: Tue 27 Nov 2012, 20:05
by technosaurus
here is an example how less comparisons can actually be bad
Code: Select all
#include <stdio.h>
int void main(){
int a=0,b=0,max=100;
char buf[500];
while(b<max/15){ //if max > 15 do blocks of 15 first
printf("%d\t%d\tFizz\t%d\tBuzz\nFizz\t%d\t%d\tFizz\tBuzz\n%d\tFizz\t%d\t%d\tFizzBuzz\n",
a+1,a+2,a+4,a+7,a+8,a+11,a+13,a+14);
a=++b*15;
}
/* now do the remainder, but in order to do 1 comparison, we must reverse
* this is _much_ slower than the comparisons so don't use it
* - just an example of how using less comparisons can be slower
* especially if doing so requires using additional slower functions
* we don't always know what the compiler will do
*/
switch(max%15){
case 14 : sprintf(buf,"%d",a+14);
case 13 : sprintf(buf,"%d\t%s",a+13,buf);
case 12 : sprintf(buf,"Fizz\t%s",buf);
case 11 : sprintf(buf,"%d\t%s",a+11,buf);
case 10 : sprintf(buf,"Buzz\n%s",buf);
case 9 : sprintf(buf,"Fizz\t%s",buf);
case 8 : sprintf(buf,"%d\t%s",a+8,buf);
case 7 : sprintf(buf,"%d\t%s",a+7,buf);
case 6 : sprintf(buf,"Fizz\t%s",buf);
case 5 : sprintf(buf,"Buzz\n%s",buf);
case 4 : sprintf(buf,"%d\t%s",a+4,buf);
case 3 : sprintf(buf,"Fizz\t%s",buf);
case 2 : sprintf(buf,"%d\t%s",a+2,buf);
case 1 : sprintf(buf,"%d\t%s",a+1,buf);
default : break
}
printf("%s",buf);
}
return 0;
}
as opposed partial unwinding to something like:
Code: Select all
#include <stdio.h>
int main(){
int a=0,b=0,max=100;
while(b<max/15){ //if max > 15 do blocks of 15 first
printf("%d\t%d\tFizz\t%d\tBuzz\nFizz\t%d\t%d\tFizz\tBuzz\n%d\tFizz\t%d\t%d\tFizzBuzz\n",a+1,a+2,a+4,a+7,a+8,a+11,a+13,a+14);
a=++b*15;
}
while (a++ < 100){
switch (a%15){
case 3 : case 6 : case 9 : case 12 : printf("Fizz\t");break;
case 5 : case 10 : printf("Buzz\n"); break;
default : printf("%d\t",a);break;
}
}
return 0;
}
btw, you can do this same algorithm in shell