De algemene FizzBuzz -implementatie die ik zag, gebruikt een vinkje voor% 15 voor “FizzBuzz” afdrukken

Zou je me willen laten weten of er iets mis / beter is met deze aanpak?

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

Reacties

  • Uw versie is geoptimaliseerd voor de computer. Winston ‘ s versie is geoptimaliseerd voor de mens. Ik moet een compiler vertrouwen dat hij goed werk kan leveren bij het opnieuw schudden en optimaliseren van de code. Het is ook mogelijk dat een enkele io-instructie sneller werkt dan twee afzonderlijke. Je zou je versie tegen de andere moeten racen.
  • Ik ‘ zal je vertellen waarom ik mijn versie beter vind (alleen voor de interviewcontext) 1) onderhoudbaarheid – je kunt Fizz en Buzz externaliseren als strings, je hoeft FizzBuzz niet ‘ te externaliseren 2) DRY, een gebruiker die de bovenstaande code schrijft, denkt in termen van zichzelf niet herhalen, wat ik leuk vind
  • +1 maar gebruik een StringBuilder en niet 100 * System.out.println (..), en Integer.valueOf (i)
  • @ cl-r bedankt, ik zal het origineel houden, zodat de opmerkingen nog steeds kloppen, bedankt voor de feedback
  • FizzBuzzEnterpriseEdition is de beste implementatie die er is: github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition ; D

Antwoord

Laten we uw versie vergelijken met de % 15 -versie:

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

De % 15 versie is sim pler en gemakkelijker te lezen. Deze versie schetst het probleem netjes in de 4 verschillende gevallen en behandelt elk geval. In tegenstelling hiermee introduceert uw versie een booleaanse logische vlag (die ik beschouw als een significant antipatroon) en een niet geheel intuïtieve afhankelijkheid van de volgorde van de if-statements.

Reacties

  • 15 is een ” magisch getal ” hier. Ik ‘ stel voor om in plaats daarvan (3 * 5) te gebruiken. De compiler zou het moeten converteren naar 15 …
  • @Ron – Zo is het, "FizzBuzz", volgens dit criterium. Niet dat je ‘ per se verkeerd bent, maar voor dit soort ‘ trivia ‘ vragen, is de noodzaak om alles aan te geven meestal een beetje versoepeld. Strikt genomen, voor code op productieniveau, alle getallen en tekenreeksen waarnaar hier wordt verwezen / afgedrukt, moeten bijvoorbeeld worden vastgelegd als benoemde constanten.
  • @ X-Zero, wilt u de 3 als constante, hoe zou je het noemen?
  • @Winston – Het algemene probleem hiermee is dat het ‘ in feite een verzonnen ‘ voorbeeld, dus het kan moeilijk zijn om hiervoor goede namen te krijgen. Vooral omdat wat de test heeft in wezen ‘ meerdere ‘ controles is – doorgaan met ontleden, zou dit waarschijnlijk resulteren in een soort array / tabelstructuur (ja … ik weet het … op weg naar de ruimte-architectuur). Dus MATCH misschien? CONDITION? Urgh. Daarom zijn dit soort conventies versoepeld voor dit soort tests; de test is voor basisvaardigheid in coderen, niet (noodzakelijkerwijs) volledige abstractievaardigheden.
  • Ik zou if-for-15 binnen if-for-5 verplaatsen, als je kunt ‘ t delen door 3, kan zeker ‘ t delen door 15, behalve 4/5 controles voor alle getallen

Antwoord

Het ziet er goed uit. String.valueOf() is niet nodig, System.out.println(i) zou hetzelfde afdrukken, maar het is nog steeds in orde. Deze test wordt alleen gebruikt om er zeker van te zijn dat de geïnterviewde code kan schrijven zoals de gelinkte site zegt:

Dit soort vragen zal geen goede programmeurs identificeren, maar het zal de zwakke identificeren. En dat is zeker een stap in de goede richting.

Antwoord

Zij zijn zeker niet perfect, maar ik heb een aantal manieren geprobeerd om de test te optimaliseren, hier het resultaat (ik heb nummers gehad om goede reacties bij te houden), en ik gebruik een StringBuilder om initialisatie van output IO te voorkomen:

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

En de uitvoer:

------ 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 

Reacties

  • StringBuilder is gebaseerd op een char[16]. Je moet de initiële capaciteit instellen op een waarde die groter is dan de String die je wilt maken – of je verslechtert de prestaties, aangezien StringBuilder moet groeien (wijs nieuwe char[] toe, kopieer oude gegevens). U moet ook weten hoe [System.nanoTime()] (stas-blogspot.blogspot.com /2012/02/what-is-behind-systemnanotime.html) werkt en de problemen die het heeft.En ik ‘ zou je aanraden om nog veel meer iteraties te doen. Ik denk dat je op dit moment voornamelijk de tijd meet voor System.out.println(), de andere bewerkingen nemen waarschijnlijk heel weinig tijd in beslag in vergelijking met een systeemoproep.
  • Vertel me, heb je ooit gehoord van het concept over-engineering …?
  • @Max Ik wel, maar is deze site bedoeld voor onderzoek of niet? Is voor comfortabele ogen, of om te proberen te begrijpen hoe sommige manieren beter zijn? U kunt dus de snellere, gemakkelijk te lezen code kiezen en vergelijken of de code opvragen om ontbrekende optimalisatie te vinden.
  • Zie Regels voor optimalisatie . IMHO Winston Ewert gaf het beste antwoord.
  • wiskunde in tabelcode uitleggen alstublieft?

Antwoord

Hier “een versie die” (IMHO) een beetje beter is voor mensen dan de jouwe en ook beter voor computers:

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

De commentaren geven informatie aan mensen (maar ze konden het nog steeds zelf zien) en er is “slechts één System.out.println aanroep per i.

EDIT: Dit is een andere manier om te bruisen (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: nog een andere, met StringBuilder, ook DROOG:

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

Reacties

  • StringBuilder lijkt een snellere aanpak dan + = in dit geval
  • @EranMedan – Weet je dit zeker? StringBuilder is goed omdat N wordt toegevoegd doesn

t leiden totNtoewijzingen, maar hier isNmaximaal 2, wat een klein genoeg om waarschijnlijk ‘ geen verschil te maken, en het ‘ is waarschijnlijk 1, wat geen verschil betekent bij all (of misschien erger, aangezienStringBuilderwaarschijnlijk een extra toewijzing doet voor die ene toevoeging).

  • @asveikau – je hebt waarschijnlijk gelijk, ik denk dat dit zal zijn over optimalisatie om erachter te komen wat precies sneller is 🙂
  • Ik ‘ ben op de hoogte van StringBuilder – die ik de hele tijd gebruik in String-zware code – en dacht mee de regels van asveikau . += is minder ” luidruchtig ” (ook de reden waarom ik Integer.toString()) en het zal ‘ niet veel verschil maken aangezien er ‘ s hoogstens twee aaneenschakelingen zijn . Btw .: ik ‘ d heb StringBuilder als volgt gebruikt: declareer voor de lus, initialiseer met capaciteit ingesteld op 8, gewist en hergebruik per iteratie. Het aanmaken binnen de lus zou niet ‘ t veel verbeteren.
  • zie hierboven voor een andere versie met StringBuilder – maar alleen één oproep naar System.out.println(...).
  • Geef een reactie

    Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *