FizzBuzzSQL

Szembe jött velem IRC-en egy, hogy

10. Solve the FizzBuzz problem with SQL code.

Oké, van egy piros x a sarokban. Vaaaaagy...

...Triviális és uncsi megoldás PostgreSQL-ben:

select i, case when i % 3 = 0 AND i % 5 = 0 then 'FizzBuzz'
 		when i % 3 = 0 then 'Fizz' 
 		when i % 5 = 0 then 'Buzz' 
 	else i::VARCHAR end
    from GENERATE_SERIES(1,100) as i

Hosszú ronda és még unalmasabb uniózással:

select i, t
from (
	SELECT i, 'Fizz'::varchar as t FROM GENERATE_SERIES(3,100,3) as i where i % 5 <> 0
	union
	SELECT i, 'Buzz'::varchar as t FROM GENERATE_SERIES(5,100,5) as i where i % 3 <> 0
	union 
	SELECT i, 'FizzBuzz'::varchar as t FROM GENERATE_SERIES(15,100,15) as i 
	union
	select i, i::VARCHAR FROM GENERATE_SERIES(1,100) as i where i % 3 <> 0 and i % 5 <> 0
) t 
order by i

Vagy a személyes kedvencemmel a LEFT JOIN-os megoldással:

select i, coalesce(f||b, f, b, i::varchar)
from generate_series(1,100) as i
	left join  (SELECT i, 'Fizz'::varchar as f FROM GENERATE_SERIES(3,100,3) as i) as ff using (i)
	left join  (SELECT i, 'Buzz'::varchar as b FROM GENERATE_SERIES(5,100,5) as i) as bb using (i)

De van itt MySQL kompatibilis megoldás:

select @num := @num+1,
  case when @num % 3 = 0 AND @num % 5 = 0 then 'FizzBuzz'
 		when @num % 3 = 0 then 'Fizz' 
 		when @num % 5 = 0 then 'Buzz' 
 	else @num end
 from ( information_schema.COLLATIONS, (select @num:=0) num ) limit 100

(Izlés szerint lehet LEFT JOIN-nal is).

és az MS SQL Server se maradjon már ki, ha kéznél van:

; WITH REC_CTE (I) AS (
	SELECT 1 AS I
	UNION ALL
	SELECT I+1 FROM REC_CTE
	WHERE I<100
)

select i, case when i % 3 = 0 AND i % 5 = 0 then 'FizzBuzz'
 		when i % 3 = 0 then 'Fizz' 
 		when i % 5 = 0 then 'Buzz' 
 	else CONVERT(VARCHAR, i) end
    from REC_CTE

Más nem volt kéznél, de még gondolkodok egy array-os megoldáson is, ha már a PostgreSQL támogatja.

Lazán kapcsolódik:
- http://blog.jooq.org/2013/11/19/how-to-create-a-range-from-1-to-10-in-s…
- http://sqlbisam.blogspot.hu/2014/01/generate-series-or-list-of-numbers…

Hozzászólások

off

azóta nem szerepel a "write a fizzbuzz algorythm in any programming language" a felvételi tesztünkben előző munkahelyem felvételi tesztjében, mióta a tisztelt IT szakértő urak kb. 90%-a instant elhasal rajta senior pozinál

/off

Ezt értem, bár meglepett, mert speciel nekem sem rémlik, hogy valaha hallottam volna róla. Szóval ez olyan, hogy én azon szoktam meglepődni, hogy IT-vel foglalkozó emberek nem ismerik a Mőbius-szalagot, ti meg nem feltételeztétek, hogy van ember, aki azt se tudja, eszik-e vagy isszák. (Nyilván ha tudja és nem tudja lekódolni, az más)

Sose hallottam még erről a játékról, de elszórakozom vele majd.

Na, ezt utálom, amikor már a whitespace spórolás is számít. Régi prog. alapjai előadó mondta mindig, hogy "tíz sorban meg tudja csinálni". Persze.

Sokkal relevánsabb lenne csak a nem whitespace karakterekben mérni az ilyen kié rövidebb kód versenyekben a hosszt.

Vagy pedig deklaráltan ugyanazzal a cb/indent paranccsal "olvashatóra" alakított kódot vizsgálni. Aki meg a C-beautifier-nek is alá dolgozik 10-100 byte-ban, az meg is érdemli :-) (Azt azért tegyük hozzá, hogy ha valaki rövid, a másik pedig hosszú változóneveket használ, az ugyanúgy nem összevethető - ezért aztán általában természetesnek tekintik, hogy 1-betűs változó-, makró- és függvénynevek szerepelnek az ilyen kódokban.

Ez a ritkább variáns, általában úgy szokott ez a fizzbuzz-téma felmerülni, hogy a jelölt egyáltalán meg tudja-e írni (például egy állásinterjún) működőre ezt a triviálisnak tekintett programot. Az a tapasztalat, hogy sokan nem tudják. A kanonikus blogbejegyzéshez (http://blog.codinghorror.com/why-cant-programmers-program/), ahol ezt felvetették, hamar született rengeteg komment, ahol minden hozzászóló kötelességének érezte prezentálni a maga minél ügyesebb megoldását, aztán a szerző egy válaszcikkben közölte, hogy igazából épp az volt a lényeg, hogy ez egy triviális feladat, és aki programozóként dolgozik (vagy akként akar dolgozni), fel sem szabadna merülnie, hogy egy ilyen triviális feladattal bármi gond legyen.

Na mindegy. Nem bírtam ellenállni a kísértésnek, íme egy kicsit rövidebb, de sokkal gonoszabb C megoldás:

http://ideone.com/k3HabD

A sztringizélő operátor bennem is felmerült, de valahogy nem akaródzott összejönni (az is igaz, hogy kb a büdös életben nem használtam, csak tudtam, hogy van). Mondjuk a kódod nekem durva, és csak tippelem, hogy pl. az "i=1" azért van a többi értékadás mellett, mert csak, így látványosabb; a vessző operátor használata pedig szintén egy tipikusan "dögöljön meg a szomszéd tehene" dolog :-) De azért gratulálok a látványos kódhoz.

A left joinos szép, a unionos is sql-es de az mégiscsak union. :)

Picit elborult az agyam és megírtam scalaban egy sorban keywordök nélkül:


(1 to 100).map(i => (Some(i).filter(_ % 3 == 0).map(_ => "Fizz") ++ Some(i).filter(_ % 5 == 0).map(_ => "Buzz")).reduceOption(_ + _).getOrElse(i))