Den fælles FizzBuzz -implementering, jeg så, bruger en check på% 15 for udskrivning “FizzBuzz”
Vil du fortælle mig, om der er noget galt / bedre med denne tilgang?
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)); } } } }
Kommentarer
- Din version er optimeret til computeren. Winston ‘ s version er optimeret til det menneskelige. Må stole på en kompilator, at den kan gøre et godt stykke arbejde med at blande og optimere koden. Det er også muligt, at en enkelt io-sætning fungerer hurtigere end to separate. Du skal køre din version mod den anden.
- Jeg ‘ Jeg fortæller dig, hvorfor jeg kan lide min version bedre (kun for interviewkonteksten) 1) vedligeholdelsesevne – du kan eksternalisere Fizz og Buzz som strenge, du behøver ‘ behøver ikke at eksternalisere FizzBuzz 2) TØRR, en bruger, der skriver ovenstående kode, tænker med hensyn til ikke at gentage sig selv, hvilket jeg kan lide
- +1 men brug en StringBuilder og ikke 100 * System.out.println (..) og Integer.valueOf (i)
- @ cl-r tak, jeg holder det i originalen, så kommentarerne stadig giver mening, tak for feedbacken
- FizzBuzzEnterpriseEdition er den bedste implementering der er: github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition ; D
Svar
Lad os sammenligne din version med % 15
version:
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
version er sim pler og lettere at læse. Denne version afgrænser pænt problemet i de 4 forskellige sager og håndterer hvert tilfælde. I modsætning hertil introducerer din version et boolesk logisk flag (som jeg anser for at være et betydeligt antimønster) og en ikke helt intuitiv afhængighed af rækkefølgen af if-udsagnene.
Kommentarer
- 15 er et ” magisk nummer ” her. Jeg ‘ jeg foreslår at bruge
(3 * 5)
i stedet. Compileren skal konvertere den til 15 … - @Ron – Således er
"FizzBuzz"
efter disse kriterier. Ikke at du ‘ er forkert nødvendigvis, men for disse typer ‘ trivia ‘ spørgsmål, nødvendigheden af at erklære alt er normalt afslappet lidt. F.eks. Skal strengt taget for produktionsniveau kode alle de numre og strenge, der refereres til / udskrives her, fanges som navngivne konstanter. - @ X-Zero, vil du fange 3 som en konstant, hvad vil du kalde det?
- @Winston – Det generelle problem med dette er, at det er ‘ s grundlæggende en ‘ konstrueret ‘ eksempel, så det kan være svært at få gode navne til dette. Især da testen har i det væsentlige ‘ multiple ‘ checks – fortsat nedbrydning vil dette sandsynligvis resultere i en slags array / tabel struktur (ja … jeg ved … på vej mod det ydre rums arkitektur). Så
MATCH
måske?CONDITION
? Urgh. Det er grunden til, at disse slags konventioner afslappes ved denne slags tests; testen er for grundlæggende kodningsevne, ikke (nødvendigvis) fuld abstraktionskompetencer. - Jeg vil flytte if-for-15 inden i if-for-5, hvis du kan ‘ t divider et tal med 3, kan bestemt ‘ t dele med 15, gemme 4/5 kontrol for alle numre
Svar
Det ser fint ud. String.valueOf()
er unødvendig. System.out.println(i)
vil udskrive det samme, men det er stadig OK. Denne test bruges kun til at sikre, at interviewpersonen kan skrive kode, som det linkede websted siger:
Denne type spørgsmål identificerer ikke gode programmører, men det vil identificere de svage. Og det er bestemt et skridt i den rigtige retning.
Svar
De er bestemt ikke perfekte, men jeg har prøvet nogle måder til at optimere testen, her er resultatet (jeg har haft tal for at holde styr på gode svar), og jeg bruger en StringBuilder for at undgå initialisering af output IO:
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; } } }
Og output:
------ 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
Kommentarer
- StringBuilder er baseret på en
char[16]
. Du skal indstille startkapaciteten til en værdi, der er større end den streng, du vil oprette – eller du forværrer ydeevnen, da StringBuilder skal vokse (tildel nyechar[]
, kopier gamle data). Du skal også være opmærksom på, hvordan [System.nanoTime()
] (stas-blogspot.blogspot.com /2012/02/what-is-behind-systemnanotime.html) fungerer og de problemer, den har.Og jeg ‘ vil råde dig til at udføre mange flere iterationer. Jeg tror, du hovedsageligt måler tiden tilSystem.out.println()
lige nu, de andre operationer tager sandsynligvis meget lidt tid i forhold til et systemopkald. - Fortæl mig, har du nogensinde hørt om konceptet over-engineering …?
- @Max jeg gør, men er dette sted lavet til nogle undersøgelser eller ej? Er det for behagelige øjne eller for at prøve at forstå, hvordan nogle måder er bedre? Så du kan vælge og sammenligne hurtigere, let at læse eller forhøre koden for at finde manglende optimering.
- Se Optimeringsregler . IMHO Winston Ewert leverede det bedste svar.
- Forklar matematik i medTabelkode tak?
Svar
Her er en version, der “(IMHO) er lidt bedre for mennesker end din og bedre for computere også:
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); } } }
Kommentarerne giver information til mennesker (men de kunne stadig se det alene) og der er kun et System.out.println
opkald pr. i
.
EDIT: Dette er en anden måde at fizz-buzz på (fokus: TØR):
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: endnu en, ved hjælp af StringBuilder
, også TØR:
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); } }
Kommentarer
- StringBuilder virker en hurtigere tilgang end + = i dette tilfælde
- @EranMedan – Er du sikker på dette?
StringBuilder
er godt, fordiN
tilføjes ikke
t fører tilN
tildelinger, men her erN
højst 2, hvilket er en lille nok antal til, at det sandsynligvis ikke vinder ‘ t gør en forskel, og det ‘ er sandsynligvis 1, hvilket betyder ingen forskel ved alt (eller måske værre, daStringBuilder
sandsynligvis foretager en ekstra fordeling for det 1 append).
+=
er mindre ” støjende ” (også grunden til min undgåelse af Integer.toString()
) og det vinder ‘ t gør meget af en forskel, da der ‘ højst er to sammenkædninger . Btw .: Jeg ‘ d har brugt StringBuilder som denne: erklær inden sløjfen, initialiser med kapacitet indstillet til 8
, ryddet og genbrug pr. iteration. Oprettelse af det inden i sløjfen ville ‘ ikke forbedre meget. StringBuilder
– men kun et opkald til System.out.println(...)
.