FizzBuzz

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Message
Author
User avatar
GustavoYz
Posts: 883
Joined: Wed 07 Jul 2010, 05:11
Location: .ar

FizzBuzz

#1 Post by GustavoYz »

I surprised myself reading this.
Is likely a very easy challenge, but effective somehow. :shock:

Im wondering if there is a bash solution (one line, not a script) shorter than this mess I just did :lol: :

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?

jamesbond
Posts: 3433
Joined: Mon 26 Feb 2007, 05:02
Location: The Blue Marble

Re: FizzBuzz

#2 Post by jamesbond »

GustavoYz wrote:Im wondering if there is a bash solution (one line, not a script) shorter than this mess I just did :lol: :

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 8)
Fatdog64 forum links: [url=http://murga-linux.com/puppy/viewtopic.php?t=117546]Latest version[/url] | [url=https://cutt.ly/ke8sn5H]Contributed packages[/url] | [url=https://cutt.ly/se8scrb]ISO builder[/url]

User avatar
GustavoYz
Posts: 883
Joined: Wed 07 Jul 2010, 05:11
Location: .ar

Re: FizzBuzz

#3 Post 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 :lol: :

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...
:roll:

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...
Attachments
FizzBuzz_NO.jpg
(24.06 KiB) Downloaded 836 times
FizzBuzz.jpg
(57.46 KiB) Downloaded 654 times

User avatar
rcrsn51
Posts: 13096
Joined: Tue 05 Sep 2006, 13:50
Location: Stratford, Ontario

#4 Post by rcrsn51 »

Is the objective to have the least amount of code or the least amount of computation?

User avatar
GustavoYz
Posts: 883
Joined: Wed 07 Jul 2010, 05:11
Location: .ar

#5 Post 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.

jamesbond
Posts: 3433
Joined: Mon 26 Feb 2007, 05:02
Location: The Blue Marble

Re: FizzBuzz

#6 Post by jamesbond »

GustavoYz wrote: And that's incorrect...
:roll:
That was an optimisation went wrong. My original version looked like this before I tried to over-optimise and remove the "continue" with || ... :lol:

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 
Fatdog64 forum links: [url=http://murga-linux.com/puppy/viewtopic.php?t=117546]Latest version[/url] | [url=https://cutt.ly/ke8sn5H]Contributed packages[/url] | [url=https://cutt.ly/se8scrb]ISO builder[/url]

User avatar
GustavoYz
Posts: 883
Joined: Wed 07 Jul 2010, 05:11
Location: .ar

Re: FizzBuzz

#7 Post 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!
:P

User avatar
L18L
Posts: 3479
Joined: Sat 19 Jun 2010, 18:56
Location: www.eussenheim.de/

FizzBuzz

#8 Post 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....

User avatar
GustavoYz
Posts: 883
Joined: Wed 07 Jul 2010, 05:11
Location: .ar

#9 Post 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. :roll:
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).

User avatar
L18L
Posts: 3479
Joined: Sat 19 Jun 2010, 18:56
Location: www.eussenheim.de/

FizzBuzz

#10 Post 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 #

User avatar
GustavoYz
Posts: 883
Joined: Wed 07 Jul 2010, 05:11
Location: .ar

#11 Post by GustavoYz »

Thanks. :D

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#12 Post 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"
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
linuph
Posts: 128
Joined: Mon 04 Jun 2012, 02:29
Location: Philippines

#13 Post by linuph »

technosaurus:
that's 0.03 user seconds on my P3 1GHz with echo to console, 0.02 with echo to file

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#14 Post 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);
}
}

}
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
rcrsn51
Posts: 13096
Joined: Tue 05 Sep 2006, 13:50
Location: Stratford, Ontario

#15 Post by rcrsn51 »

technosaurus wrote:

Code: Select all

switch (n%15){
Very nice. Doing three divisions is clearly overkill. Doing one division is better.

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#16 Post by technosaurus »

rcrsn51 wrote:
technosaurus wrote:

Code: Select all

switch (n%15){
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.
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
GustavoYz
Posts: 883
Joined: Wed 07 Jul 2010, 05:11
Location: .ar

#17 Post by GustavoYz »

@technosaurus: Nice, thanks. :D

jamesbond
Posts: 3433
Joined: Mon 26 Feb 2007, 05:02
Location: The Blue Marble

#18 Post 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 :shock:

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
Fatdog64 forum links: [url=http://murga-linux.com/puppy/viewtopic.php?t=117546]Latest version[/url] | [url=https://cutt.ly/ke8sn5H]Contributed packages[/url] | [url=https://cutt.ly/se8scrb]ISO builder[/url]

User avatar
rcrsn51
Posts: 13096
Joined: Tue 05 Sep 2006, 13:50
Location: Stratford, Ontario

#19 Post 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.

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#20 Post 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
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

Post Reply