Yleinen FizzBuzz -toteutus, jonka näin, käyttää tarkistusta% 15: lle ”FizzBuzz” -tulostaminen
Ilmoittaisitko, jos tässä lähestymistavassa on jotain vikaa / parempaa?
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)); } } } }
Kommentit
- Versiosi on optimoitu tietokonetta varten. Winston ’ -versio on optimoitu ihmiselle. On luotettava kääntäjään, että se voi tehdä hyvää työtä koodin uudelleen sekoittamisessa ja optimoinnissa. On myös mahdollista, että yksi io-lause toimii nopeammin kuin kaksi erillistä lausetta. Sinun tulisi verrata versiota toiseen.
- Minä ’ kerron, miksi pidän versiostani paremmin (vain haastatteluyhteydessä) 1) ylläpidettävyys – voit ulkoistaa Fizzin ja Buzzin merkkijonoina, sinun ei tarvitse ’ ulkoistaa FizzBuzz 2) DRY, yllä olevaa koodia kirjoittava käyttäjä ajattelee olemaan toistamatta itseään, mistä pidän
- +1, mutta käytä StringBuilder , älä 100 * System.out.println (..) ja Integer.valueOf (i)
- @ cl-r kiitos, pidän sen alkuperäisessä, joten kommenteilla on silti järkevää, kiitos palautteesta.
- FizzBuzzEnterpriseEdition on paras toteutus: github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition ; D
Vastaa
Vertaa verrataan versiotasi % 15
-versioon:
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
-versio on sim pler ja helpompi lukea. Tämä versio rajaa ongelman siististi neljään eri tapaukseen ja käsittelee jokaisen tapauksen. Sen sijaan versiossasi otetaan käyttöön looginen logiikkalippu (jota pidän merkittävänä anti-mallina) ja ei täysin intuitiivinen riippuvuus if-lausekkeiden järjestyksestä.
kommentit
- 15 on ” maaginen numero ” täällä. Ehdotan ’ käyttämistä sen sijaan
(3 * 5)
. Kääntäjän tulisi muuntaa se arvoksi 15 … - @Ron – Niin on,
"FizzBuzz"
, tällä ehdolla. Ei siitä, että ’ olet väärässä välttämättä, mutta tämän tyyppisille ’ trivia ’ kysymykset, kaiken ilmoittamisen välttämättömyys on yleensä lievennetty. Esimerkiksi tarkasti ottaen tuotantotason koodin kaikki tähän viitatut / tulostetut numerot ja merkkijonot tulisi kaapata nimettyinä vakioina. - @ X-Zero, ottaisitko 3 vakiona, mitä sinä sitä kutsuisit?
- @Winston – Yleinen ongelma tässä on se, että ’ on pohjimmiltaan ’ keksitty ’ esimerkki, joten voi olla vaikea saada hyviä nimiä tälle. Varsinkin kun testillä on olennaisesti ’ useita ’ -tarkistuksia – hajottamisen jatkaminen johtaisi todennäköisesti jonkinlaiseen taulukko- / taulukkorakenteeseen (joo … tiedän … suuntaan avaruusarkkitehtuuriin). Joten,
MATCH
ehkä?CONDITION
? Urgh. Siksi tämäntyyppiset yleissopimukset lieventävät tällaisia kokeita; testi koskee perustietokoodausta, ei (välttämättä) täydellisiä abstraktiotaitoja. - Liikkun if-for-15: n sisällä if-for-5: n suhteen, jos voit ’ t jaa numero 3: lla, ei varmasti voi ’ t jakaa 15: llä, tallenna 4/5 kaikkien numeroiden tarkastuksista
Vastaa
Se näyttää hyvältä. String.valueOf()
on tarpeeton, System.out.println(i)
tulosta sama, mutta se on silti OK. Tätä testiä käytetään vain varmistamaan, että haastateltava voi kirjoittaa koodin linkitetyn sivuston sanojen mukaan:
Tällainen kysymys ei tunnista suuria ohjelmoijia, mutta se tunnistaa heikot. Ja se on ehdottomasti askel oikeaan suuntaan.
Vastaa
He eivät todellakaan ole täydellisyyksiä, mutta olen kokeillut joitain tapoja testin optimoimiseksi, tässä tulos (minulla on ollut numeroita hyvien vastausten jäljittämiseksi) ja käytän StringBuilderia välttääksesi IO: n alustamisen:
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; } } }
Ja lähtö:
------ 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
kommentit
- StringBuilder perustuu
char[16]
-kohtaan. Aseta alkukapasiteetti arvoksi, joka on suurempi kuin luotava merkkijono – tai heikennät suorituskykyä, koska StringBuilderin täytyy kasvaa (varaa uudetchar[]
, kopioi vanhat tiedot). Sinun tulisi myös olla tietoinen siitä, miten [System.nanoTime()
] (stas-blogspot.blogspot.com /2012/02/what-is-behind-systemnanotime.html) toimii ja sen ongelmat.Ja minä ’ neuvoisin sinua tekemään paljon enemmän iteraatioita. Luulen, että mittaat pääasiassaSystem.out.println()
-aikaa juuri nyt, muut toiminnot vievät todennäköisesti hyvin vähän aikaa järjestelmän puheluun verrattuna. - Kerro minulle, oletko koskaan kuullut käsitteestä ylisuunnittelu …?
- @Max I do, mutta onko tämä sivusto tehty joillekin tutkimuksille vai ei? Onko miellyttävät silmät, tai yrittää ymmärtää, miten jotkut tavat ovat parempia? Joten voit valita ja vertailla nopeampaa, helppolukuisempaa tai kysellä koodia löytääksesi puuttuvan optimoinnin.
- Katso optimointisäännöt . IMHO Winston Ewert antoi parhaan vastauksen.
- selittää matematiikka taulukon koodilla?
Vastaa
Tässä on versio, joka on (IMHO) ihmisille hieman parempi kuin sinun ja parempi myös tietokoneille:
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); } } }
Kommentit tarjoavat tietoa ihmisille (mutta he voisivat silti nähdä sen yksin), ja siellä on vain yksi System.out.println
kutsu i
.
MUOKKAA: Tämä on toinen tapa levittää (tarkennus: KUIVA):
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); } } }
MUOKKAA 2: vielä yksi, käyttäen StringBuilder
, myös kuiva:
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); } }
kommentit
- StringBuilder näyttää nopeammalta lähestymistavalta kuin + = tässä tapauksessa
- @EranMedan – Oletko varma tästä?
StringBuilder
on hyvä, koskaN
lisää ei
t ei johdaN
jakamiseen, mutta tässäN
on korkeintaan 2, mikä on tarpeeksi pieni luku, että se todennäköisesti voitti ’ t, tekee eron, ja se ’ on todennäköisesti 1, mikä tarkoittaa, ettei eroa kaikki (tai ehkä pahempaa, koskaStringBuilder
todennäköisesti tekee ylimääräisen varauksen tälle 1 liitteelle).
+=
on vähemmän ” meluisa ” (myös syy välttää Integer.toString()
) ja se ei voittanut ’ t paljon eroa, koska ’ on enintään kaksi ketjutusta . Btw .: Olen ’ d käyttänyt StringBuilderia näin: julista ennen silmukkaa, alusta kapasiteetilla, joka on asetettu 8
, tyhjennetään ja käytetään uudelleen per iterointi. Sen luominen silmukan sisään ei parantaisi paljoakaan ’. StringBuilder
– mutta vain yksi puhelu numeroon System.out.println(...)
.