5 ms·
Fizz Buzz without conditionals or booleans
- stop50 1y agoAnswer: Modulo or adding "%3" and "%5" before masking it
- deleted 1y ago[deleted]
- unsnap_biceps 1y agoMuch like stop50's solution, I also used the modulo, but I make use of the terminal to overwrite the number. It's only three lines of code, but I split up the list to be more readable on here. This works from 1 to 100000000000000000000 before it overflows, and 100000000000000000000 is above the max size of a unsigned 64 bit int, so I feel that it's good enough fizzbuzz = [ "fizzbuzz ", "", "", "fizz ", "", "buzz ", "fizz ", "", "", "fizz ", "buzz ", "", "fizz ", "", "" ] for n in range(99999999999999999999-30, 100000000000000000000): print(f"{n}\r{fizzbuzz[n%15]}")
- floxy 11mo agoVery nice.
- kiratp 11mo agoA for loop has an implicit conditional in its stop condition check.
- kstrauser 11mo agoI could see that both ways. Python’s for loops are different than, say, C’s, in that they always consume an iterator. The implementation is that it calls next(iter) until it raises a StopIteration exception, but you could argue that’s just an implementation detail and not cheating. If you wanted to be more general, you could use map() to apply the function to every member of the iterator, and implementation details aside, that feels solidly in the spirit of the challenge.
- hug 11mo agoThe dirty solution I wrote in Powershell does something similar: 1..100 | % {"$_ $(('fizz','')[$_%3])$(('buzz','')[$_%5])"} I am not sure that using [$_%3] to index into a two-value array doesn't count as a "disguised boolean" thought.
- brudgers 1y agoNo matter how you calculate FizzBuzz, it is bad engineering. const Fizzbuzz = "1 2. Fizz, 4 ... " Print Fizzbuzz
- hyperhello 11mo agoWhat’s the point of the game without booleans?
- LanceH 11mo agopackage main import ( "fmt" "math/rand" ) var fb [4]string = [4]string{"", "fizz", "buzz", "fizzbuzz"} var lucky int64 = 176064004 func main() { for i := 1; i <= 100; i++ { if i%15 == 1 { rand.Seed(lucky) } fmt.Printf("%d: %s\n", i, fb[rand.Int63()%4]) } }
- frosting1337 11mo agoThere's a conditional, though?
- albedoa 11mo agoYeah this is weird. It's against the rules to speculate about whether a commenter read the article, but what about the title of the article?
- LanceH 11mo agoI did, in fact, read the article. I've offered my subversive FizzBuzz as an alternative. It's not according to the article's rules, but it's definitely against the grain of the normal FizzBuzz.
- bluGill 11mo agoI always wanted to write this with duff's device. switch with fall through is almost never a good thing but it allows for some 'interesting' tricks. Wouldn't be hard, but I have kids so finding half an hour to concentrate is hard.
- dullcrisp 11mo agovim +'exec "norm 99o"|%s/$/\=line(".")/|vert new|exec "norm i\r\rFizz\r\rBuzz\rFizz\r\r\rFizz\rBuzz\r\rFizz\r\r\rFizzBuzz"|exec "norm gg\<c-v>G$y"|bd!|let @q="10a \<esc>\"0gpj"|exec "norm gg10@q"|silent /100/+,$d|silent %s/\d\+\s\+\(\w\+\)/\1' Now I see it's the same solution as in the post. Edit: Actually all you need is vim -es +'exec "norm! i\r\rFizz\r\rBuzz\rFizz\r\r\rFizz\rBuzz\r\rFizz\r\r\rFizzBuzz\<esc>Vggy7P101GdG"|%s/^$/\=line(".")/|%p|q!'
- HWR_14 11mo agoWhat's a "disguised Boolean" in this context?
- gridspy 11mo agoI'd imagine that as any variable that only has two states.
- nucleogenesis 11mo agoI think it was more about doing it without a Boolean-based branch construct like a ternary or switch or whatever flavor of thing that abstracts away the explicit checks for true/false by other means. Idk though for sure
- deleted 11mo ago[deleted]
- kqr 11mo agoSomething like this: https://entropicthoughts.com/fizzbuzz-through-monoids https://entropicthoughts.com/fizzbuzz-through-monoids
- swisniewski 11mo agoSigh… Saying the code doesn’t have conditions or booleans is only true if you completely ignore how the functions being called are being implemented. Cycle involves conditionals, zip involves conditionals, range involves conditionals, array access involves conditionals, the string concatenation involves conditionals, the iterator expansion in the for loop involves conditionals. This has orders of magnitude more conditionals than normal fizz buzz would. Even the function calls involve conditionals (python uses dynamic dispatch). Even if call site caching is used to avoid repeated name lookups, that involves conditionals. There is not a line of code in that file (even the import statement) that does not use at least one conditional. So… interesting implementation, but it’s not “fizzbuzz without booleans or conditionals”.
- swisniewski 11mo agoNot sure why this got downvoted. The technique could be implemented without conditionals, but not in python, and not using iterators. You could do it in C, and use & and ~ to make the cyclic counters work. But, like I mentioned, the code in the article is very far from being free of conditionals.
- abustamam 11mo agoI didn't down vote, but it does seem like unnecessary pedantry. Maybe it could be better phrased as "without writing any conditionals"
- kstrauser 11mo agoI think that’s kind of vacuously true. Like, good luck writing this in any language where the resulting assembler all the way at the bottom of the runtime has zero branch operations. And I bet even then that most CPUs’ microcode or superscalar engine would have conditionals underlying the opcodes. I’d settle for just not writing conditionals in the user’s own code. Range doesn’t have to be implemented with branches. Hypothetically, Python could prefill a long list of ints, and range could return the appropriate slice of it. That’d be goofy, of course, but the main idea is that the user doesn’t know or really care exactly how range() was written and optimized.
- somat 11mo agoEnumerating all values probably can't be done in python as that requires some sort of unchecked loop construct, that is a goto or bare loop nether of which is present in python. perhaps a recursive solution(throws up a little in mouth) baring that I too got nerd sniped by this and unsatisfied by the limitations of the authors solution here is my attempt. and when I read up on fizzbuz to make sure I was solving the correct thing. (I was not and my elegant duel state engine was wasted) it turns out the problem solution could be as simple as f_out = ['', '', 'fizz'] b_out = ['', '', '', '', 'buzz'] def fizz_buz(n): return(f_out[n % 3] + b_out[n % 5]) anyhow the rest of my clever but unneeded and useless enumeration system, remember to read the spec first. f_state = { 0:1, 1:2, 2:0, } b_state = { 0:1, 1:2, 2:3, 3:4, 4:0, } def fizz_buzz_all(): f_index = 0 b_index = 0 while 1: #how to loop with no end check? print(f_out([f_index] + b_out[b_index] ) f_index = f_state[f_index] b_index = b_state[b_index] and the recursive solution: def fizz_buzz_recurse(n): print(fizz_buzz(n)) fizz_buzz_recurse(n + 1)
- soxfox42 11mo agoThat solution fails for any value that is a multiple of neither 3 nor 5. In those cases, the result should be the original number.
- somat 11mo agoSigh, Even after I reread the spec... I did not in fact read the spec. complete failure on my part.
- drdeca 11mo agoYou can replace `while 1:` with `for x in iter(int, 1):` .
- jeremysalwen 11mo agoMake it throw an exception with an index out of bounds to terminate the loop.
- cestith 11mo agoWhat exactly are we counting as “a conditional”? Is it only “if” statements? Do “case” or “switch” statements count? Do loops with loop conditions count? Do all the included functions being abused count for all the conditionals in them? Do short-circuited boolean operations count, or only boolean variables? I mean, if we want to play fast and loose with those definitions then this also has no conditionals and no booleans.(Warning: Perl, somewhat golfed) $s = '', $i % 3 || ($s .= 'fizz'), $i % 5 || ($s .= 'buzz'), $s ||= $i, print "$s\n" while (++$i < 101)
- userbinator 11mo agochallenged listeners to “write Fizz Buzz with no booleans, no conditionals, no pattern matching, or other things that are like disguised booleans.” Without any other constraints, this is not an interesting challenge. print("<precalculated output goes here>")
- moritzwarhier 11mo agoprompt("please enter the expected output of a solution to the fizz buzz problem, without any further enclosing text or explanations; especially: do not enter program code") should work in a browser JS environment (with layer 8) and with modern AI
- kiratp 11mo agoA for loop has a conditional in it. Unless by conditionals we mean “no if/else” and not “no branch instructions”.
- WhyNotHugo 11mo agoThe conditional here only makes it stop when it reaches 100. The solution can be adapted to use a while loop if you’re okay with it running indefinitely.
- kiratp 11mo agoA loop either never halts or has a conditional. I guess a compiler could elide a “while True:” to a branch-less jump instruction. One hack would be to use recursion and let stack exhaustion stop you.
- nodja 11mo agoCount down i from 100 to 0 and do 1/i at the end of the loop :)
- buzer 11mo agoOther would be to use goto (though Python doesn't have it) & introduce something that will panic/throw exception, like creating variable with value 1/(max-i).
- pinusc 11mo agoRecursion would work for that, you don't need goto. The division by zero trick is pretty good too!
- deleted 11mo ago[deleted]
- TZubiri 11mo agoYou could allocate 100 bytes and get a segfault on 101
- brudgers 11mo agoObviously FizzBuzz is a property of integers Integer extend [ fizzbuzz [ (self \\ 15 = 0) ifTrue: ['fizzbuzz' printNl] ifFalse: [ (self \\ 3 = 0) ifTrue: ['fizz' printNl] ifFalse: [ (self \\ 5 = 0) ifTrue: ['buzz' printNl] ifFalse: [self printNl] ] ] ] ] 1 to: 100 by: 1 do: [:i | i fizzbuzz]
- kstrauser 11mo agoHow about: print(filter(None, [f + b, str(n)])[0]) Would that be not-Boolean enough?
- MathMonkeyMan 11mo agoHere's my attempt: # Multi-pass FizzBuzz n = 100 # [['1'], ['2'], ['3'], ['4'], ['5'], ...] seq = [[str(i)] for i in range(1, n + 1)] # [['1'], ['2'], ['3', 'Fizz'], ['4'], ['5'], ...] for i in range(3, n + 1, 3): seq[i-1].append('Fizz') # [['1'], ['2'], ['3', 'Fizz'], ['4'], ['5', 'Buzz'], ..., ['15', ''Fizz', 'Buzz'], ...] for i in range(5, n + 1, 5): seq[i-1].append('Buzz') # Arithmetic equivalent to: # len=1 -> the whole thing (from zero to end, because zero = -zero) # len=2 -> the length-1 suffix (just Fizz or Buzz) # len=3 -> the length-2 suffix (Fizz and Buzz) # The branch is hidden in the slice syntax: # Python has to check whether `x` is negative in `terms[x:]`. for terms in seq: print(''.join(terms[-(len(terms) - 1):])) Here's a version that uses generators instead of multiple passes over a list: # Single-pass FizzBuzz n = 100 def numbers(): for i in range(1, n+1): yield [str(i)] def fizzies(): nums = numbers() try: while True: yield next(nums) yield next(nums) yield [*next(nums), 'Fizz'] except StopIteration: pass def buzzies(): fzs = fizzies() try: while True: yield next(fzs) yield next(fzs) yield next(fzs) yield next(fzs) yield [*next(fzs), 'Buzz'] except StopIteration: pass for terms in buzzies(): print(''.join(terms[-(len(terms) - 1):])) Edit: Can't resist -- unbounded without loops, but recursion blows the call stack (granted, well after 100): def numbers(i=1): yield [str(i)] yield from numbers(i+1) def fizzies(source=numbers()): yield next(source) yield next(source) yield [*next(source), 'Fizz'] yield from fizzies(source) def buzzies(source=fizzies()): yield next(source) yield next(source) yield next(source) yield next(source) yield [*next(source), 'Buzz'] yield from buzzies(source) def main(source=buzzies()): terms = next(source) print(''.join(terms[1-len(terms):])) main(source) main()
- andriamanitra 11mo agoI gave it a go in C (I wanted to do assembly but couldn't be arsed to write string to int and int to string conversions). [1] The trickiest part was figuring out how to terminate the program. My first attempt invoked nasal demons through dividing by zero, but I then realized I could intentionally cause a segfault with high probability (which is much better, right?). One could argue that my `fizz` and `buzz` variables are still "disguised booleans", but at least the generated assembly contains no branching or cmov instructions (aside from the ones inside libc functions like atoi and sprintf). [1] https://gist.github.com/Andriamanitra/5c20f367dc4570dd5c8068824fe8cfe6 https://gist.github.com/Andriamanitra/5c20f367dc4570dd5c8068...
- mapehe 11mo agoThis is pretty cool, actually
- sovnwnt 11mo ago> No disguised booleans Do indexes count? If not, there's a simple one liner def fizzbuzz(n): return [str(n), "fizz", "buzz", "fizzbuzz"][1-min(1, n%3) + (1-min(1,n%5))*2]
- Mikhail_Edoshin 11mo agoWhat is the canonical formulation of FizzBuzz?
- genewitch 11mo agoi've seen worse than this sort of thing: https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition/blob/uinverse/src/main/java/com/seriouscompany/business/java/fizzbuzz/packagenamingpackage/impl/math/arithmetics/NumberIsMultipleOfAnotherNumberVerifier.java https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...
- ramenprofitable 11mo agoThe suckless approach #include <stdio.h> #include <stdint.h> #include <stdlib.h> void fizzbuzz(int i) { uint32_t r3 = i % 3; uint32_t r5 = i % 5; uint32_t is_nonzero_3 = (r3 | -r3) >> 31; uint32_t is_nonzero_5 = (r5 | -r5) >> 31; uint32_t is_zero_3 = is_nonzero_3 ^ 1; uint32_t is_zero_5 = is_nonzero_5 ^ 1; uint32_t idx = (is_zero_5 << 1) | is_zero_3; const char *fmt[] = { "%d\n", "Fizz\n", "Buzz\n", "FizzBuzz\n" }; printf(fmt[idx], i); } typedef void (*func_t)(int); void run_loop(int i); void stop_loop(int i) { exit(0); } func_t actions[] = { stop_loop, run_loop }; void run_loop(int i) { fizzbuzz(i); int d = 99 - i; uint32_t is_neg = ((uint32_t)d) >> 31; } func_t actions_table[] = { run_loop, stop_loop }; void run_loop_wrapper(int i) { fizzbuzz(i); int d = 99 - i; uint32_t is_neg = ((uint32_t)d) >> 31; actions_table[is_neg](i + 1); } int main() { actions_table[0] = run_loop_wrapper; run_loop_wrapper(1); return 0; }
- jswelker 11mo ago3 lines of python, no imports. fizzbuzz = [None, None, "Fizz", None, "Buzz", "Fizz", None, None, "Fizz", "Buzz", None, "Fizz", None, None, "FizzBuzz"] for i in range(1,100): print(fizzbuzz[i % 15] or i) Edit: I see I was a few hours late, and someone posted nearly the exact same solution. :(
- genewitch 11mo agodoes not "or" imply a boolean
- jswelker 11mo agoIt does.Will you accept max? fizzbuzz = ["", "", "Fizz", "", "Buzz", "Fizz", "", "", "Fizz", "Buzz", "", "Fizz", "", "", "FizzBuzz"] for i in range(1,101): print(max((fizzbuzz[(i-1)% 15],str(i),))) Probably still bools under the hood.
- TZubiri 11mo agoDoesn't a for loop contain a conditional? (If i <101)
- jswelker 11mo agoThat is in arbitrary line I am willing to draw in the battle against pedantry. Surely though a fizzbuzz isn't supposed to run forever though right? Gotta end it somehow, and the for loop is idiomatic.
- TZubiri 11mo agoIt's a challenge and you can do whatever version you want. If I'm pedantring about it it's because it can be done with a stricter restriction (or at least I think it can be done). I'd also add that it isn't a particularly hard problem, so I would recommend that if you are having trouble with solving for the hardest interpretation of the problem, that you keep on trying because there is quite a simple solution. If I were hiring based on this, your answer is a pass for sure. But it isn't exactly clear to me that you know about cpu comparisions or conditional jumps. In fact I think if you knew about them you wouldn't call it an arbitrary line. I think there is a python solution as a prototype, but of course the robust solution would be in python to ensure control over the cpu instructions and avoid conditionals for good.
- susam 11mo agoLate to the party but here's a solution I worked out using roots of unity and cosines: from math import cos, pi for n in range(1, 101): print([n, 'Fizz', 'Buzz', 'FizzBuzz'][round((1 + 2 * cos(2 * pi * n / 3)) / 3 + 2 * (1 + 2 * cos(2 * pi * n / 5) + 2 * cos(4 * pi * n / 5)) / 5)])
- nik9000 11mo agoAs it should be.
- pbiggar 11mo agoSimple solution using modulo arithmetic and arrays. Relies on python shorthands that hides implicit branches for the number case though. def main(): fizz_array = ["Fizz", "", ""] buzz_array = ["Buzz", "", "", "", ""] for n in range(1, 101): # Use modulo to index into arrays f = fizz_array[n % 3] b = buzz_array[n % 5] # Combine fizz and buzz result = f + b output = result + str(n)[len(result):] print(output) main() I couldn't figure out this line and had to rely on AI for it. output = result + str(n)[len(result):]
- seanhunter 11mo agofrom itertools import cycle fizz = cycle(["","","fizz"]) buzz = cycle(["","","","","buzz"]) for z in zip(fizz,buzz): print(f"{z[0]}{z[1]}")
- bjoli 11mo agoWhen I find a problem I can solve with ciclical structures I always feel like Da Vinci. Fizzbuzz is probably the perfect fit, which is sad since it is a synthetic problem. I did find one problem once where I could save about 30s of user waiting time by generating (had to be done dynamically) wheels in the 3-10k element range.
- throwaway150 11mo agoDoesn't look right. The numbers are missing from the output. If you don't print the numbers, sure it's trivial.
- seanhunter 11mo agoI didn't know that was a requirement. OK then from itertools import cycle fizz = cycle(["","","fizz"]) buzz = cycle(["","","","","buzz"]) for idx, z in enumerate(zip(fizz,buzz)): print(f"{idx}: {z[0]}{z[1]}") Happy now?
- throwaway150 11mo agoThis doesn't look right either. You should really look up what FizzBuzz is. The output should be like: 1 2 fizz 4 buzz fizz You can't just print the number for every line. Check this out - https://rosettacode.org/wiki/FizzBuzz https://rosettacode.org/wiki/FizzBuzz or just run the program in the OP which prints correct output.
- seanhunter 11mo agoI should really look it up because it’s such an important thing to get canonically correct.
- qrian 11mo agoitertools.count is probably what OP is looking for