Den gemensamma FizzBuzz -implementeringen jag såg använder en check på% 15 för skriva ut ”FizzBuzz”

Skulle du meddela mig om det är något fel / bättre med detta tillvägagångssätt?

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 är optimerad för datorn. Winstons ’ -version är optimerad för människan. Måste lita på en kompilator att den kan göra ett bra jobb med att blanda om och optimera koden. Det är också möjligt att ett enda io-uttalande fungerar snabbare än två separata. Du bör tävla med din version mot den andra.
  • Jag ’ Jag berättar varför jag gillar min version bättre (endast för intervjusammanhang) 1) underhåll – du kan externisera Fizz och Buzz som strängar, du behöver inte ’ att externa FizzBuzz 2) TORR, en användare som skriver ovanstående kod tänker i termer av att inte upprepa sig själv, vilket jag gillar
  • +1 men använd en StringBuilder och inte 100 * System.out.println (..) och Integer.valueOf (i)
  • @ cl-r tack, jag kommer att behålla den på originalet så att kommentarerna fortfarande är vettiga, tack för feedback
  • FizzBuzzEnterpriseEdition är den bästa implementeringen som finns: github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition ; D

Svar

Låt oss jämföra 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 versionen är sim pler och lättare att läsa. Denna version beskriver problemet snyggt i de fyra olika fallen och hanterar varje fall. Däremot introducerar din version en boolesk logisk flagga (som jag anser vara ett betydande antimönster) och ett inte helt intuitivt beroende av ordningen på if-uttalandena.

Kommentarer

  • 15 är ett ” magiskt nummer ” här. Jag ’ föreslår att jag använder (3 * 5) istället. Kompilatorn ska konvertera den till 15 …
  • @Ron – Så är det, "FizzBuzz", enligt dessa kriterier. Inte för att du ’ är fel nödvändigtvis, men för dessa typer av ’ trivia ’ frågor, nödvändigheten av att förklara allt är vanligtvis avslappnad något. Till exempel, strängt taget, för kod på produktionsnivå, bör alla siffrorna och strängarna som refereras till / skrivas ut här fångas som namngivna konstanter.
  • @ X-Zero, skulle du fånga 3 som en konstant, vad skulle du kalla det?
  • @Winston – Det allmänna problemet med detta är att det är ’ s i princip en ’ konstruerat ’ exempel, så det kan vara svårt att få bra namn för detta. Speciellt eftersom testet i huvudsak är ’ flera ’ kontroller – om du fortsätter att sönderdela detta skulle det sannolikt resultera i någon form av array / tabellstruktur (ja … jag vet … på väg mot yttre rymdarkitektur). Så, MATCH kanske? CONDITION? Urgh. Det är därför som denna typ av konventioner är avslappnad för denna typ av test; testet är för grundläggande kodningsförmåga, inte (nödvändigtvis) fullständiga abstraktionskunskaper.
  • Jag skulle flytta if-for-15 inuti if-for-5, om du kan ’ t dela ett tal med 3, kan definitivt ’ t dela med 15, spara 4/5 kontroller för alla nummer

Svar

Det ser bra ut. String.valueOf() är onödigt, System.out.println(i) skulle skriva ut samma men det är fortfarande OK. Detta test används bara för att säkerställa att intervjuaren kan skriva kod som den länkade webbplatsen säger:

Denna typ av fråga kommer inte att identifiera bra programmerare, men det kommer att identifiera de svaga. Och det är definitivt ett steg i rätt riktning.

Svar

De är verkligen inte perfekta, men jag har provat några sätt att optimera testet, här är resultatet (jag har haft siffror för att hålla koll på bra svar), och jag använder en StringBuilder för att undvika initialisering av 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; } } } 

Och utmatningen:

------ 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 är baserad på en char[16]. Du bör ställa in den initiala kapaciteten till ett värde större än strängen du vill skapa – eller så försämrar du prestandan eftersom StringBuilder måste växa (tilldela ny char[], kopiera gamla data). Du bör också vara medveten om hur [System.nanoTime()] (stas-blogspot.blogspot.com /2012/02/what-is-behind-systemnanotime.html) fungerar och de problem det har.Och jag ’ rekommenderar att du gör mycket fler iterationer. Jag tror att du huvudsakligen mäter tiden för System.out.println() just nu, de andra operationerna tar förmodligen väldigt lite tid jämfört med ett systemanrop.
  • Berätta, har du någonsin hört talas om konceptet överteknik …?
  • @ Max gör jag, men är den här webbplatsen gjord för vissa undersökningar eller inte? Är det för bekväma ögon, eller för att försöka förstå hur vissa sätt är bättre? Så du kan välja och jämföra snabbare, lättläst eller förhöra koden för att hitta optimering som saknas.
  • Se Optimeringsregler . IMHO Winston Ewert gav det bästa svaret.
  • förklara matematik med tabellkod tack?

Svar

Här är en version som ”s (IMHO) är lite bättre för människor än din och bättre för datorer också:

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); } } } 

Kommentarerna ger information till människor (men de kunde fortfarande se det på egen hand) och det finns bara ett System.out.println samtal per i.

EDIT: Det här är ett annat sätt att fizz-buzz (fokus: 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: ännu en, med StringBuilder, TORR också:

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 verkar en snabbare strategi än + = i det här fallet
  • @EranMedan – Är du säker på detta? StringBuilder är bra eftersom N läggs till inte

t leder tillNallokeringar, men härNär högst 2, vilket är en tillräckligt litet antal för att det troligtvis inte kommer att vinna ’ t, och det ’ är troligtvis 1, vilket betyder ingen skillnad vid allt (eller kanske värre, eftersomStringBuilderantagligen gör en extra tilldelning för det 1 tillägget).

  • @asveikau – du har nog rätt, jag antar att detta kommer att vara över optimering för att ta reda på exakt vilken som är snabbare 🙂
  • Jag ’ är medveten om StringBuilder – som jag använder hela tiden i String tung kod – och tänkte med raderna i asveikau . += är mindre ” bullriga ” (också orsaken till att jag undviker Integer.toString()) och det vann ’ t gör stor skillnad eftersom ’ är högst två sammankopplingar . Btw .: Jag ’ d har använt StringBuilder så här: deklarera före slingan, initialisera med kapacitet inställd på 8, rensas och återanvändas iteration. Att skapa det inuti slingan skulle inte ’ inte förbättras mycket.
  • se ovan för en annan version med StringBuilder – men bara ett samtal till System.out.println(...).
  • Lämna ett svar

    Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *