Implementarea obișnuită Implementarea FizzBuzz pe care am văzut-o utilizează o verificare pentru% 15 pentru imprimarea „FizzBuzz”

Mi-ați anunța dacă există ceva greșit / mai bun în această abordare?

public class FizzBuzz { public static void main(String[] args) { for (int i = 1; i <= 100; i++) { boolean fizzOrBuzz = false; if (i % 3 == 0) { System.out.print("Fizz"); fizzOrBuzz = true; } if (i % 5 == 0) { System.out.print("Buzz"); fizzOrBuzz = true; } if (fizzOrBuzz) { System.out.println(); } else { System.out.println(String.valueOf(i)); } } } } 

Comentarii

  • Versiunea dvs. este optimizată pentru computer. Versiunea Winston ‘ este optimizată pentru om. Trebuie să am încredere într-un compilator că poate face o treabă bună la redistribuirea și optimizarea codului. De asemenea, este posibil ca o singură declarație io să funcționeze mai repede decât două instrucțiuni separate. Ar trebui să luptați cu versiunea dvs. cu cealaltă.
  • Vă ‘ vă voi spune de ce îmi place versiunea mea mai bine (numai pentru contextul interviului) 1) mentenabilitate – puteți externaliza Fizz și Buzz ca șiruri de caractere, nu aveți nevoie ‘ de exteriorizarea FizzBuzz 2) DRY, un utilizator care scrie codul de mai sus se gândește în termeni de a nu se repeta, ceea ce îmi place
  • +1 dar, utilizați un StringBuilder și nu 100 * System.out.println (..) și Integer.valueOf (i)
  • @ cl-r mulțumesc, îl voi păstra la original, astfel încât comentariile să aibă sens, mulțumesc pentru feedback
  • FizzBuzzEnterpriseEdition este cea mai bună implementare: github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition ; D

Răspuns

Comparăm versiunea cu versiunea % 15:

public class FizzBuzz { public static void main(String[] args) { for (int i = 1; i <= 100; i++) { if (i % 15 == 0) { System.out.println("FizzBuzz") } else if (i % 3 == 0) { System.out.println("Fizz"); } else if (i % 5 == 0) { System.out.println("Buzz"); } else { System.out.println(String.valueOf(i)); } } } } 

% 15 versiunea este sim mai ușor și mai ușor de citit. Această versiune descrie cu grijă problema în cele 4 cazuri diferite și gestionează fiecare caz. În schimb, versiunea dvs. introduce un flag logic boolean (pe care îl consider a fi un anti-model semnificativ) și o dependență nu în întregime intuitivă de ordinea instrucțiunilor if.

Comentarii

  • 15 este un ” număr magic ” aici. ‘ sugerez să folosiți în schimb (3 * 5). Compilatorul ar trebui să-l convertească la 15 …
  • @Ron – La fel, "FizzBuzz", după acest criteriu. Nu că ‘ te greșești în mod necesar, ci pentru aceste tipuri de ‘ trivia ‘ întrebări, necesitatea de a declara totul este de obicei ușor relaxată. De exemplu, strict vorbind, pentru codul la nivel de producție, toate numerele și șirurile menționate / tipărite aici ar trebui capturate ca constante numite.
  • @ X-Zero, ați captura 3 ca o constantă, cum l-ați numi?
  • @Winston – Problema generală cu aceasta este că ‘ este practic inventat ‘, deci poate fi greu să obții nume bune pentru acest lucru. Mai ales că testul are în esență ‘ verificări multiple ‘ – continuarea descompunerii ar duce probabil la un fel de structură matrice / tabel (da … știu … îndreptându-mă spre arhitectura spațiului cosmic). Deci, MATCH poate? CONDITION? Urgh. Motiv pentru care aceste tipuri de convenții sunt relaxate pentru aceste tipuri de teste; testul este pentru abilitatea de codare de bază, nu (neapărat) abilități complete de abstractizare.
  • M-aș deplasa if-for-15 în interiorul if-for-5, dacă poți ‘ nu împărțiți un număr la 3, cu siguranță ‘ nu puteți împărți cu 15, salvați 4/5 din cecuri pentru toate numerele

Răspuns

Arată bine. String.valueOf() nu este necesar, System.out.println(i) ar imprima la fel, dar este în continuare OK. Acest test este utilizat numai pentru a vă asigura că persoana intervievată poate scrie codul așa cum spune site-ul conectat:

Acest tip de întrebare nu va identifica marii programatori, dar îi va identifica pe cei slabi. Și acesta este cu siguranță un pas în direcția corectă.

Răspuns

Ei cu siguranță nu sunt perfecte, dar am încercat câteva modalități de a optimiza testul, aici rezultatul (am avut numere pentru a păstra urme de răspunsuri bune) și folosesc un StringBuilder pentru a evita inițializarea IO de ieșire:

package exercices; import java.util.Hashtable; import org.memneuroo.outils.communs.utilitaires.EnvPrm; public class FizzBuzz { // time for cum with nbIter=30 > 300; 30 ~= 3000 static final int nbIter = 30; static final String sep = "_"; static long ifNested() { final StringBuilder sb = new StringBuilder(); final long t = System.nanoTime(); for (int i = 0; i < nbIter; i++) { sb.append(// i % 15 == 0 // ? "FizzBuzz" // : (i % 3 == 0 // ? "Fizz"// : (i % 5 == 0// ? "Buzz" // : i)));// sb.append(sep); } final long totT = System.nanoTime() - t; System.out.format("ifNested\t%20d\n", totT); // sb.append(EnvPrm.NEWLINE); System.out.println(sb.toString()); return totT; } static long stringPlus() { final StringBuilder sb = new StringBuilder(); final long t = System.nanoTime(); for (int i = 0; i < nbIter; i++) { String x = ""; x += (i % 3 == 0) ? "Fizz" : ""; x += (i % 5 == 0) ? "Buzz" : ""; if (x.isEmpty()) { // MODIF x += Integer.toString(i); } sb.append(x);// sb.append(sep); } final long totT = System.nanoTime() - t; System.out.format("stringPlus\t%20d\n", totT); // sb.append(EnvPrm.NEWLINE); System.out.println(sb.toString()); return totT; } static long withIf() { final StringBuilder sb = new StringBuilder(); final long t = System.nanoTime(); for (int i = 0; i < nbIter; i++) { if (i % 3 == 0) { sb.append("Fizz"); if (i % 5 == 0) { sb.append("Buzz"); } } else if (i % 5 == 0) { sb.append("Buzz"); } else { sb.append(i); }// sb.append(sep); } final long totT = System.nanoTime() - t; System.out.format("withIf\t\t%20d\n", totT); // sb.append(EnvPrm.NEWLINE);System.out.println(sb.toString()); return totT; } static long withArray() { final String[] lis = {"FizzBuzz", "", "", "Fizz", "", "Buzz", "Fizz", "", "", "Fizz", "Buzz", "", "Fizz", "", "",}; final StringBuilder sb = new StringBuilder(); final long t = System.nanoTime(); for (int i = 0; i < nbIter; i++) { final String pos = lis[i % 15]; sb.append(((0 == pos.length()) ? i : pos));// sb.append(sep); } final long totT = System.nanoTime() - t; System.out.format("withArray\t%20d\n", totT); // sb.append(EnvPrm.NEWLINE); System.out.println(sb.toString()); return totT; } static long withTable() { final Hashtable<Integer, String> ht = new Hashtable<>(8); ht.put(0, "FizzBuzz"); ht.put(3, "Fizz"); ht.put(5, "Buzz"); ht.put(6, "Fizz"); ht.put(9, "Fizz"); ht.put(10, "Buzz"); ht.put(12, "Buzz"); final StringBuilder sb = new StringBuilder(); final long t = System.nanoTime(); for (int i = 0; i < nbIter; i++) { final String s = ht.get(i % 15); // MODIF // http://www.developpez.net/forums/d1196563-2/java/general-java/if-null-object-if-objet-null/#post6561766 // sb.append((null == s ? i : s));// sb.append(sep); if (null == s) { sb.append(i); } else { sb.append(s); } } final long totT = System.nanoTime() - t; System.out.format("withTable\t%20d\n", totT); // sb.append(EnvPrm.NEWLINE); System.out.println(sb.toString()); return totT; } static int recursive(final StringBuilder sb, final int n) { if (0 == n) { return 1; } if (n % 3 == 0) { sb.insert(0, "Fizz"); if (n % 5 == 0) { sb.insert(0, "Buzz"); } } else if (n % 5 == 0) { sb.insert(0, "Buzz"); } else { sb.insert(0, n); } return n + recursive(sb, n - 1); } static long recursive() { final StringBuilder sb = new StringBuilder(""); final long t = System.nanoTime(); recursive(sb, nbIter); final long totT = System.nanoTime() - t; System.out.format("recursive\t%20d\n", totT); sb.append(EnvPrm.NEWLINE); System.out.println(sb.toString()); return totT; } /*** @param args */ public static void main(final String[] args) { long cum = 0L, cum2 = 0L; for (int i = 0; i < 5; i++) { System.out.println("------ " + i + " -----"); final long totSb = stringPlus(); final long totIn = ifNested(); final long totWi = withIf(); final long totWa = withArray(); final long totWt = withTable(); final long totRe = recursive(); System.out.format("... stringPlus/withIf :%5d\n", (totSb * 100) / totWi); System.out.format("... ifNested/withIf :%5d\n", (totIn * 100) / totWi); System.out.format("... withArray/withIf :%5d\n", (totWa * 100) / totWi); System.out.format("... withTable/withIf :%5d\n", (totWt * 100) / totWi); System.out.format("... recursive/withIf :%5d\n", (totRe * 100) / totWi); cum += totIn + totSb + totWi + totWa + totWt + totRe; System.out.println("CUMUL (SECOND) == " + cum / 100000000 + "." + cum % 100000000 + "\t , diff: " + (cum - cum2)); cum2 = cum; } } } 

Și rezultatul:

------ 0 ----- stringPlus 529397 ifNested 643657 withIf 27657 withArray 43581 withTable 40788 recursive 87441 12Fizz4BuzzFizz78FizzBuzz11Fizz1314BuzzFizz1617Fizz19BuzzFizz2223FizzBuzz26Fizz2829BuzzFizz ... stringPlus/withIf : 1914 ... ifNested/withIf : 2327 ... withArray/withIf : 157 ... withTable/withIf : 147 ... recursive/withIf : 316 CUMUL (SECOND) == 0.1372521 , diff: 1372521 ------ 1 ----- stringPlus 345295 ifNested 88280 withIf 88279 withArray 88838 withTable 101689 recursive 93308 12Fizz4BuzzFizz78FizzBuzz11Fizz1314BuzzFizz1617Fizz19BuzzFizz2223FizzBuzz26Fizz2829BuzzFizz ... stringPlus/withIf : 391 ... ifNested/withIf : 100 ... withArray/withIf : 100 ... withTable/withIf : 115 ... recursive/withIf : 105 CUMUL (SECOND) == 0.2178210 , diff: 805689 ------ 2 ----- stringPlus 380216 ifNested 36597 withIf 20953 withArray 60063 withTable 91352 recursive 111467 12Fizz4BuzzFizz78FizzBuzz11Fizz1314BuzzFizz1617Fizz19BuzzFizz2223FizzBuzz26Fizz2829BuzzFizz ... stringPlus/withIf : 1814 ... ifNested/withIf : 174 ... withArray/withIf : 286 ... withTable/withIf : 435 ... recursive/withIf : 531 CUMUL (SECOND) == 0.2878858 , diff: 700648 ------ 3 ----- stringPlus 489168 ifNested 29613 withIf 22070 withArray 27099 withTable 27378 recursive 91911 12Fizz4BuzzFizz78FizzBuzz11Fizz1314BuzzFizz1617Fizz19BuzzFizz2223FizzBuzz26Fizz2829BuzzFizz ... stringPlus/withIf : 2216 ... ifNested/withIf : 134 ... withArray/withIf : 122 ... withTable/withIf : 124 ... recursive/withIf : 416 CUMUL (SECOND) == 0.3566097 , diff: 687239 ------ 4 ----- stringPlus 143035 ifNested 24025 withIf 15924 withArray 23187 withTable 26819 recursive 87162 12Fizz4BuzzFizz78FizzBuzz11Fizz1314BuzzFizz1617Fizz19BuzzFizz2223FizzBuzz26Fizz2829BuzzFizz ... stringPlus/withIf : 898 ... ifNested/withIf : 150 ... withArray/withIf : 145 ... withTable/withIf : 168 ... recursive/withIf : 547 CUMUL (SECOND) == 0.3886249 , diff: 320152 

Comentarii

  • StringBuilder se bazează pe un char[16]. Ar trebui să setați capacitatea inițială la o valoare mai mare decât șirul pe care doriți să îl creați – sau veți agrava performanța, deoarece StringBuilder trebuie să crească (alocați char[] noi, copiați datele vechi). De asemenea, ar trebui să știți cum [System.nanoTime()] (stas-blogspot.blogspot.com /2012/02/what-is-behind-systemnanotime.html) funcționează și problemele pe care le are.Și ‘ vă sfătuiesc să faceți mult mai multe iterații. Cred că măsurați în principal timpul pentru System.out.println() chiar acum, celelalte operații probabil că durează foarte puțin în comparație cu un apel de sistem.
  • Spuneți-mi, ați avut vreodată ați auzit de conceptul over-engineering …?
  • @Max, dar este acest site făcut pentru unele cercetări sau nu? Este pentru ochi confortabili sau pentru a încerca să înțelegeți cum unele modalități sunt mai bune? Astfel, puteți alege și compara cel mai rapid, mai ușor de citit sau interogați codul pentru a găsi lipsa optimizării.
  • Consultați Reguli pentru optimizare . IMHO Winston Ewert a oferit cel mai bun răspuns.
  • explicați matematica cu codul Tabel, vă rog?

Răspundeți

Aici „o versiune care este (IMHO) puțin mai bună pentru oameni decât a ta și mai bună și pentru computere:

public class FizzBuzz { public static void main(String[] args) { for (int i = 1; i <= 100; i++) { String value; switch (i % 15) { case 3: case 6: case 9: case 12: // divisible by 3, print Fizz value = "Fizz"; break; case 5: case 10: // divisible by 5, print Buzz value = "Buzz"; break; case 0: // divisible by 3 and by 5, print FizzBuzz value = "FizzBuzz"; break; default: // else print the number value = Integer.toString(i); } System.out.println(value); } } } 

Comentariile oferă informații pentru oameni (dar totuși au putut să o vadă singuri) și există un singur System.out.println apel pe i.

EDIT: Acesta este un alt mod de a fizz-buzz (focus: DRY):

public class FizzBuzz { public static void main(String[] args) { final String EMPTY = ""; for (int i = 1; i <= 100; i++) { String value = EMPTY; if (i % 3 == 0) value += "Fizz"; if (i % 5 == 0) value += "Buzz"; if (value == EMPTY) value += i; System.out.println(value); } } } 

EDIT 2: încă un altul, folosind StringBuilder, și DRY:

public class FizzBuzz { public static void main(String[] args) { StringBuilder builder = new StringBuilder(1000); for (int i = 1; i <= 100; i++) { final int length = builder.length(); if (i % 3 == 0) builder.append("Fizz"); if (i % 5 == 0) builder.append("Buzz"); if (length == builder.length()) builder.append(i); builder.append("\n"); } System.out.println(builder); } } 

Comentarii

  • StringBuilder pare o abordare mai rapidă decât + = în acest caz
  • @EranMedan – Sunteți sigur de acest lucru? StringBuilder este bun deoarece N se adaugă nu

nu duce la alocăriN, totuși aiciNeste cel mult 2, ceea ce reprezintă un un număr suficient de mic încât să câștige probabil ‘ pentru a face diferența și ‘ este destul de probabil să fie 1, ceea ce înseamnă că nu există nicio diferență la totul (sau poate mai rău, deoareceStringBuilderface probabil o alocare suplimentară pentru acea 1 anexă).

  • @asveikau – probabil ai dreptate, cred că va fi peste optimizare pentru a afla exact ce este mai rapid 🙂
  • Sunt ‘ conștient de StringBuilder – pe care îl folosesc tot timpul în codul greu String – și m-am gândit liniile asveikau . += este mai puțin ” zgomotos ” (și motivul pentru care am evitat Integer.toString()) și a câștigat ‘ nu face o mare diferență, deoarece există ‘ cel mult două concatenări . Btw .: Am ‘ aș fi folosit StringBuilder astfel: declarați înainte de buclă, inițializați cu capacitatea setată la 8, ștergeți și reutilizați repetare. Crearea acestuia în buclă nu ‘ nu se va îmbunătăți mult.
  • vezi mai sus pentru o altă versiune folosind StringBuilder – dar numai un apel către System.out.println(...).
  • Lasă un răspuns

    Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *