Pár motivačných riadkov na úvod
Áno - (ne)budeme (ne)súťažiť. Zapojiť sa môže ktokoľvek, kto má aspoň 6 rokov (je tu silný predpoklad, že jedinec už dokáže písať a čítať) a menej ako 666 rokov (pri tejto výške veku existuje zasa silný predpoklad toho, že sa tohto veku nikto nedožije a teda nebude nutné počas najbližších N rokov túto hranicu posúvať vyššie a vyššie). A (ne)má súťaživého ducha. Súťaž predsa znamená istú prestíž, meranie síl, vedomostí a schopností. Ale prináša so sebou aj rozličné zmiešané pocity typu "Ja na to nemám." alebo slovenskejšie "Ja sa tam strápnim". Áno - aj toto všetko táto (ne)pravidelná (ne)súťaž so sebou obnáša.
Súťaž? Čo môžem vyhrať?
Aby bolo jasné hneď na začiatku, vyhrať (ne)môžete nič. Však to poznáte - nie je dôležité vyhrať, ale zúčastniť sa. V zmysle tohto (ne)overeného a (ne)prekonateľného sloganu mnohých (ne)úspešných a trápnosť zaháňajúcich súťažiacich sa budeme riadiť aj my. Takže ak očakávate kadejaké Xkrabice (z orig. Xbox), alebo jaPodložky (z orig. iPad), ste určite na (ne)správnom mieste.
Kde sa zaregistrujem?
Tí zdatnejší už určite porozumeli, že nikde. Respektíve, ak chcete po sebe zanechať hlbokú stopu a kopec odkazov na internete na vaše (chabé)úžazné výsledky, zaregistrujte sa na tomto portáli. Ale ak sa (ne)chcete strápňovať, radšej tak vôbec (ne)robte. Ešte by si o vás podaktorí súťažiaci (alebo blízki priatelia) začali myslieť veci, ktoré by naozaj odrážali skutočnosť (že to bol fakt trapas).
Aj tak to risknem - aké sú pravidlá?
Žiadne. Teda jediné - pri (ne)súťažení sa snažte konať aspoň ako tak športovo bez podvádzania. Ale nikto (a ja už vôbec nie) vám nezakazuje, aby ste nepoužívali všetky internetové zdroje na dosiahnutie svojho nehynúceho a na veky obdivovaného výsledku.
Tak poďme na to. Aká je dnešná piatková úloha?
Úloha? O tom tu ešte nebolo nič napísané. Niekto predbieha. Ale k veci - (ne)pravidelná piatková (ne)súťaž bude naozaj o riešení úloh. (Ne)budú to však matematické úlohy, ale možno občas budú. (Ne)budú to linuxové úlohy, ale možno tiež občas budú. Budeme cvičiť logické-programátorské-skriptovacie-linuxácke-matematické-fyzikálne-herné-doplňčochceš myslenie. Ale ako (ne)praví linuxáci sa budeme snažiť hlavne o tie linuxácke riešenia. Vytvorené pomocou nástrojov, ktoré máte v tom Linuxe voľne dostupné. Môžete teda programovať, skriptovať, kresliť, … Cieľ bude pochváliť sa práve svojím riešením. A budeme sa kochať rozličnými spôsobmi a rozličnými riešeniami tej istej úlohy.
Nuda. Chcem súťažiť!
Keďže sa dnes jedná o jubilejné prvé kolo, začneme s niečím jednoduchým, aby sme (ne)odradili každého čitateľa, ktorý sa tu náhodou vyskytol. Začneme s úlohou s názvom Fizz-Buzz.
Round #1: Fizz-Buzz
Táto úloha je vo svete IT veľmi známa, pretože sa z času na čas objaví na niektorom prijímacom pohovore kadejakého programátora. Aj keď je úplne jednoduchá, vie aj potrápiť. Vašou úlohou je napísať program (kľudne aj skript), ktorý dostane jeden vstupný parameter N, ktorým bude celé kladné číslo. Tento program postupne vypíše čísla od 1 po N, pričom:
- Ak je číslo deliteľné 3, miesto tohto čísla sa na obrazovku vypíšte text
fizz. - Ak je však číslo deliteľné 5, miesto tohto čísla sa na obrazovku vypíše text
buzz. - Ak je však číslo deliteľné naraz aj číslom 3 aj 5, vypíše sa miesto tohto čísla na obrazovku text
fizzbuzz.
Pre tých menej chápavých ale rovnako nadšených uveďme príklad - ak program dostane na vstupe hodnotu 20, výstup bude vyzerať nasledovne:
1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizzbuzz 16 17 fizz 19 buzz
Jednoduché, že? Tak na čo ešte čakáte? Štartujte svoje nadupané stroje (Javy, Pionierov, Simsonov, Barborky, …) a pustite sa do riešenia tejto (ne)náročnej úlohy. Pri jej publikovaní nezabudnite uviesť, o aký jazyk (ak ste programovali) sa jedná. A nebojte sa - ak niekto už stihol problém vyriešiť vo vašom naj(ne)obľúbenejšom jazyku, kľudne pripojte aj svoje riešenie - určite ho dotyčný nespravil tak zle, ako vy.
Držím palce! Nech (ne)zvíťazí ten najlepší!

ruby -e '1.upto(ARGV[0].to_i) {|i| if i%3==0 and i%5==0 then print "fizzbuzz\n" elsif i%3==0 then print "fizz\n" elsif i%5==0 then print "buzz\n" else print "#{i}\n" end}' 20
ruby -e '1.upto(ARGV[0].to_i) {|i| case ((i%3==0 and 1 or 0) + (i%5==0 and 2 or 0)) when 3; print "fizzbuzz\n" when 1; print "fizz\n" when 2; print "buzz\n" else print "#{i}\n" end}' 20
prosim ta - skus svoje riesenie zapisat do elementu <pre>, aby sme sa my ostatni (ne)sutaziaci vedeli inspirovat a kochat tvojim riesenim...
ale samozrejme - gratulujem ku prvemu (ne)sutaznemu prispevku. mas velku sancu (ne)vyhrat, nakolko pocet (ne)sutaznych prispevkov je aktualne 1.
Žiaľ (ne)prispejem, mne to pripadá ako (ne)prepis eposu o Gilgamešovi zo Starobabylončiny do latinky :)
+1
C++ (ne)používam, tak sám seba (ne)pochválim.
#include <iostream> #include <stdlib.h> using namespace std; int main(int argc, char **argv){ int i=atoi(argv[1]),p=0; for(int x=1; x<i+1; ++x) { if (x%3==0) {p+=1; } if (x%5==0) {p+=2; } if (p==0) {cout<<x<<endl; } else{if (p==1) {cout<<"fizz"<<endl; } if (p==2) {cout<<"buzz"<<endl; } if (p==3) {cout<<"fizzbuzz"<<endl; }} p=0; } return 0; }Nejak sa mi to celé včera nechcelo čítať :) tak dnes riešenie v PHP:
for ($i=1; $i<21; $i++) { if ($i%3 == 0) {echo "fizz";} if ($i%5 == 0) {echo "buzz";} if ($i%3 && $i%5) {echo $i;} echo PHP_EOL; }Ešte pridávam C++ verziu:
#include <iostream> using namespace std; int main () { for (int $i=1; $i<21; $i++) { if ($i%3 == 0) {cout << "fizz";} if ($i%5 == 0) {cout << "buzz";} if ($i%3 && $i%5) {cout << $i;} cout << endl; } }nepochopené zadanie :)
počet sa má programu nejako zadať :)
OK, opravené, ale to že všetci zbytočne vypisujú "fizzbuzz" ti nevadí? :-D
#include <iostream> #include <cstdlib> using namespace std; int main (int argc, char** argv) { int loops = atoi (argv[1]); for (int $i=1; $i<=loops; $i++) { if ($i%3 == 0) {cout << "fizz";} if ($i%5 == 0) {cout << "buzz";} if ($i%3 && $i%5) {cout << $i;} cout << endl; } }Sú ľudia čo sa spoliehajú na vlastný rozum a sú aj taký čo sa spoliehajú na automatické optimalizácie.
optimalnejsie je vypisat fizzbuz ako 2x pouzit std::ostream na fizz a buzz :)
Možné to je, ale ešte je otázka čo vyprodukuje kompilátor a ešte keď sa človek pohrá s optimalizáciami kompilátora ako písal Juraj.
g++, O3, http://gcc.godbolt.org/, navestia .L24, .L5 a .L11
std::ctype<char>::do_widen(char) const: mov eax, esi ret .LC0: .string "fizz" .LC1: .string "buzz" main: push r13 push r12 mov edx, 10 push rbp push rbx sub rsp, 8 mov rdi, QWORD PTR [rsi+8] xor esi, esi call strtol test eax, eax jle .L15 mov r12d, eax mov ebx, 1 mov ebp, 1431655766 jmp .L19 .L27: movsx esi, BYTE PTR [r13+67] .L8: mov edi, OFFSET FLAT:std::cout add ebx, 1 call std::basic_ostream<char <char> >::put(char) mov rdi, rax call std::basic_ostream<char <char> >::flush() cmp ebx, r12d jg .L15 .L19: mov eax, ebx mov r13d, ebx imul ebp sar r13d, 31 sub edx, r13d lea eax, [rdx+rdx*2] cmp ebx, eax je .L24 mov eax, ebx mov edx, 1717986919 imul edx sar edx sub edx, r13d lea eax, [rdx+rdx*4] cmp ebx, eax jne .L25 .L11: mov edx, 4 mov esi, OFFSET FLAT:.LC1 mov edi, OFFSET FLAT:std::cout call std::basic_ostream<char <char> >& std::__ostream_insert<char <char> >(std::basic_ostream<char <char> >&, char const*, long) .L5: mov rax, QWORD PTR std::cout[rip] mov rax, QWORD PTR [rax-24] mov r13, QWORD PTR std::cout[rax+240] test r13, r13 je .L26 cmp BYTE PTR [r13+56], 0 jne .L27 mov rdi, r13 call std::ctype<char>::_M_widen_init() const mov rax, QWORD PTR [r13+0] mov esi, 10 mov rax, QWORD PTR [rax+48] cmp rax, OFFSET FLAT:std::ctype<char>::do_widen(char) const je .L8 mov rdi, r13 call rax movsx esi, al jmp .L8 .L25: mov esi, ebx mov edi, OFFSET FLAT:std::cout call std::basic_ostream<char <char> >::operator<<(int) jmp .L5 .L24: mov edx, 4 mov esi, OFFSET FLAT:.LC0 mov edi, OFFSET FLAT:std::cout call std::basic_ostream<char <char> >& std::__ostream_insert<char <char> >(std::basic_ostream<char <char> >&, char const*, long) mov eax, ebx mov edx, 1717986919 imul edx sar edx sub edx, r13d lea eax, [rdx+rdx*4] cmp ebx, eax jne .L5 jmp .L11 .L15: add rsp, 8 xor eax, eax pop rbx pop rbp pop r12 pop r13 ret .L26: call std::__throw_bad_cast() sub rsp, 8 mov edi, OFFSET FLAT:std::__ioinit call std::ios_base::Init::Init() mov edx, OFFSET FLAT:__dso_handle mov esi, OFFSET FLAT:std::__ioinit mov edi, OFFSET FLAT:std::ios_base::Init::~Init() add rsp, 8 jmp __cxa_atexitcout << endl; <- zbytocne, drahe volanie, efektivnejsie cout << '\n';
Totok sa mi moc nechce veriť, v čom je problém? Chápem že prekladač to zdrží, ale v skompilovanom programe to už bude podľa platformy, či?
std::endl vola std::flush, co je vo vacsine pripadou nepotrebne. takisto
je pomalsie akoassembly pre std::cout << std::endl;
*pripadov :)
To neva, ja mám rád eleganciu :-) Ale aj tak dík za rozbor.
Python
Na konci docela zaujímavo a jednoducho riešené v python2.
Uf tak takéto zneužitie operátorov sa len tak často nevidí ;)
#include <iostream> #include <string> #include <stdexcept> using std::ostream; using std::cout; using std::stoi; class FizzBuzz final { private: int mTo; public: explicit FizzBuzz(int to) : mTo {to} { }; friend ostream& operator<<(ostream& os, const FizzBuzz& fb); }; ostream& operator<<(ostream& os, const FizzBuzz& fb) { for (int i = 1; i <= fb.mTo; ++i) { if (i % 5 == 0 && i % 3 == 0) os << "fizzbuzz"; else if (i % 3 == 0) os << "fizz"; else if (i % 5 == 0) os << "buzz"; else os << i; os << '\n'; } return os; } int main(int argc, char** argv) { if (argc != 2) return -1; try { FizzBuzz fb(stoi(argv[1])); cout << fb; } catch (std::invalid_argument& ex) { cout << ex.what(); return -1; } catch (std::out_of_range& ex) { cout << ex.what(); return -1; } return 0; }kto prvy napise riesenie v BRAINFUCK? heh.
https://gist.github.com/cammckinnon/2369233
haaaaa... vyhravas cenu tyzdna. Najlepsi googlic na linuxos.... :) . fakt som neveril ze to uz niekto riesil na nete :)
#!/bin/bash n="$1" seq 1 "$n" | factor | sed 's/\( 2\| 7\| [0-9]\{2,\}\)//g' | sed 's/\([0-9]*:\)\( 3\)\+/fizz/' | sed 's/\([0-9]*:\)\?\( 5\)\+/buzz/' | tr -d ':'for (int i = 1; i <= 20; i++) cout << !(i % 3) ? !(i % 5) ? "fizzbuzz" : "fizz" : !(i % 5) ? "buzz": itoa(i) << endl;
#include <stdio char* itoa(int val){ static char buf[32] = {0}; int i = 30; for(; val && i; i--, val/= 10) buf[i] = "0123456789abcdef"[val % 10]; return &buf[i+1]; } int main() { int i; for (i = 1; i <= 20; i++) puts(!(i % 3) ? !(i % 5) ? "fizzbuzz" : "fizz" : !(i % 5) ? "buzz" : itoa(i)); return 0; }