24
\$\begingroup\$

Background

The Zundoko Kiyoshi function originates from this tweet by kumiromilk. Translated from Japanese, it reads roughly as follows:

The test for my Java lecture had a problem that said "Implement and describe your own function". I made it continuously output either "zun" or "doko" randomly; if the sequence "zun", "zun", "zun", "zun", "doko" appears, it outputs "ki-yo-shi!" and terminates. Then I got full marks and earned a unit.

This is in reference to Kiyoshi Hikawa's song Kiyoshi no Zundoko Bushi: when he sings the aforementioned line, the crowd cheers "ki-yo-shi!" in response.

Task

Write a program or function that takes no input and replicates the behavior outlined in the tweet:

  • Repeatedly output either zun or doko, choosing uniformly randomly each time.
  • If the sequence ["zun", "zun", "zun", "zun", "doko"] appears in the output, output ki-yo-shi! and halt.

Example output:

doko
zun
zun
doko
doko
zun
zun
zun
zun
zun
doko
ki-yo-shi!

Rules

  • This is , so shortest answer in bytes wins.
  • Your output can be a list of strings, or each string printed with some delimiter.
  • Your output has to be non-deterministic.
\$\endgroup\$
  • 5
    \$\begingroup\$ "your output has to be non-deterministic" - is it allowed to alternate between zun and doko forever and randomize the starting word? \$\endgroup\$ – my pronoun is monicareinstate May 8 at 3:02
  • \$\begingroup\$ "your output has to be non-deterministic" - does employing pseudo-random numbers count as being non-deterministic? \$\endgroup\$ – Λ̸̸ May 8 at 3:06
  • 1
    \$\begingroup\$ @mypronounismonicareinstate No. It has to be capable of eventually producing the sequence mentioned in the challenge, and endlessly alternating between the two strings doesn't allow for that. \$\endgroup\$ – sporeball May 8 at 3:27
  • \$\begingroup\$ @Λ̸̸ Yes, unless you use the exact same seed for the PRNG every time. \$\endgroup\$ – sporeball May 8 at 3:41
  • 2
    \$\begingroup\$ @xnor I think uniform randomness is what I meant when I wrote "random"; being capable of producing the ending sequence is by no means the only requirement. \$\endgroup\$ – sporeball May 8 at 6:15

20 Answers 20

3
\$\begingroup\$

Jelly, 36 bytes

2Xµị“zun“doko”Ṅȧ;ɼḄß“ki-yo-shi!”%?32

A full program which takes no input and prints as it runs.

Try it online!

How?

2Xµị“zun“doko”Ṅȧ;ɼḄß“ki-yo-shi!”%?32 - Main Link (no arguments)
2                                    - literal two
 X                                   - random number in [1..x] -> z = 1 or 2
  µ                                  - start a new monadic chain, f(z)
    “zun“doko”                       - list of strings = ["zun", "doko"]
   ị                                 - index into -> v = "zun" or "doko"
              Ṅ                      - print v and a newline and yield v
               ȧ                     - (v) logical AND (z) -> z 
                 ɼ                   - recall from the register (initially 0), apply
                                     -     the following and store the result back
                                     -     into the register:
                ;                    -   concatenate
                  Ḅ                  - convert from base-2 (e.g. [0,2,1,1,1,1,2] -> 96
                                     -     since 0×2⁶+2×2⁵+1×2⁴+1×2³+2×2²+1×2¹+2×2°=96)
                                 ?   - if...
                                % 32 - ...condition: modulo 32 (is non-zero)
                   ß                 - ...then: call this Link again (Main Link)
                    “ki-yo-shi!”     - ...else: string "ki-yo-shi!"
                                     - implicit print
| improve this answer | |
\$\endgroup\$
12
\$\begingroup\$

JavaScript (ES6), 72 bytes

f=x=>x%17^2?['doko ','zun '][j=Math.random()*2|0]+f(x<<7|j):'ki-yo-shi!'

Try it online!

How?

We keep track of the last 5 words in a 32-bit integer stored in \$x\$ (which is initially undefined). At each iteration, we left-shift it by 7 positions and set the LSB to \$0\$ for doko or \$1\$ for zun.

The sequence zun, zun, zun, zun, doko results in:

x = 10000001000000100000010000000

or \$270549120\$ in decimal, which is the only value for which we have \$x\equiv 2\pmod{17}\$, as shown in this table. This is our halt condition.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ f=x=>1-~x&31?['doko ','zun '][j=Math.random()*2|0]+f(x*2|j):'ki-yo-shi!' same 72B, no need =2mod17 \$\endgroup\$ – l4m2 May 13 at 18:24
7
\$\begingroup\$

05AB1E, 54 50 44 43 42 39 37 bytes

[.•BΓßb¥•#TΩDˆè¯J30bÅ¿#}"ki-yo-shi!"»

Try it online!

I doubt string compression is going to help here. Prove me wrong. It did help. -5 thanks to @Kevin

Forgive me, Adnan, for writing such a long program.

Explained (old)

[1ÝΩ

First of all, we start an infinite loop, generate the range [0, 1] and pick a random object from that list.

D

We then duplicates that random number for later use.

.•BΓßb¥•#

Next, we push the compressed string "doko zun" and split it upon spaces.

sè,

Then, we swap that splitted string and the randomly generated number from earlier and index the string at that position. , prints the word to STDOUT.

ˆ¯5.£J

Here's where the fun begins. After the indexing and printing, we are left with the original random number on the stack. We append it to the global array and then push the global array to obtain the last 5 items from the list. This will be a string of 1s and 0s. The joining is simply to mould the list into a single string.

30b

We then convert the number 30 into its binary representation: 11110. This represents four zuns followed by a doko, as that's the order they appear in the compressed string from earlier.

Q#]

Then, we check to see if the last 5 items (which we joined into a string) is equal to the binary of 30. If it is, the infinite loop will stop, moving on to the next step. Otherwise, the above steps are repeated again.

"ki-yo-shi!",

At this stage, the loop has finished, meaning all that is left to do is print the required end string.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ 39 bytes: -1 by changing 1ÝΩ to ; -1 by removing both , and using a trailing » instead to join the stack; and -1 by changing the position of the TΩD so you won't need the s. \$\endgroup\$ – Kevin Cruijssen May 8 at 9:03
  • \$\begingroup\$ @KevinCruijssen wow, I don't know how I missed that. Thanks! \$\endgroup\$ – Lyxal May 8 at 9:08
  • 1
    \$\begingroup\$ Oh, and another -2 by changing ¯5.£J30bQ to ¯J30bÅ¿. :) (PS: My name isn't Keven ;p) \$\endgroup\$ – Kevin Cruijssen May 8 at 9:09
  • 1
    \$\begingroup\$ @KevinCruijssen aw h*ck. Sorry about that! \$\endgroup\$ – Lyxal May 8 at 9:13
  • \$\begingroup\$ Np, it isn't the first time my name is misspelled like that, haha ;) \$\endgroup\$ – Kevin Cruijssen May 8 at 9:34
7
\$\begingroup\$

C#, 347 255 170 119 115 92 Bytes

for(int k=3;k!=1;Write(k%2<1?"zun ":"doko "))k=k<<7^new Random().Next(2);Write("ki-yo-shi!")

Explanation

// Only every 7th bit changes
// k is set to three so that the code won't terminate until
// at least 5 shifts have occured
// Terminate when k is one
// so that every 7th bit matches 00001
for(int k=3;k!=1;){
    k=k<<7;
    // Shift the bits in k
    k=k^new Random().Next(2);
    // Set the last bit to random value
    Write(k%2<1?"zun ":"doko ")
    // Output zun or doko based on last bit 
//zun = 0, doko = 1. kiyoshi = 00001
}
//we only get here if we have 00001
Write("ki-yo-shi!")

Try it online!

Added a TIO link and also saved almost 100 bytes :) (Not counting the class Program + static void Main() declarations and also implied using System).

My friends and I went back and forth with what I had originally and ended up with this. Basically cut the bytes in half. You can potentially run out of memory in the rare scenario that you never get a kiyoshi but whatever.

Thanks to Kevin and monicareinstate in the comments, this is now 119 bytes. Using the interactive compiler instead you can put functions outside of the main function and it implies using.

Last edit: we got this to 92 bytes! Can't even believe it given how verbose C# is.

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ Hi, welcome to CGCC! Your program current continues looping even after printing "ki-yo-shi!". I think you forgot a break; in that if-block to terminate your infinite loop. :) As for some golfing tips: you are allowed to use (lambda) functions instead of full programs by default, which saves a lot of bytes in verbose languages like C#. Also, if you haven't seen it yet, tips for golfing in C# and tips for golfing in <all languages> might be interesting to read through. \$\endgroup\$ – Kevin Cruijssen May 8 at 9:40
  • 2
    \$\begingroup\$ it would also be beneficial to add a TIO- link, so other can verify your program more easily (like almost all other answers have as well). :) Here is the one for your program - with the additional break;) I will first let you try to golf it a bit more yourself with the tips in my comment above, but if you want I could golf the code and explain what I've shortened. Enjoy your stay! :) \$\endgroup\$ – Kevin Cruijssen May 8 at 9:42
  • 1
    \$\begingroup\$ Thanks, Kevin, for being so helpful! I'm admittedly not good with lambdas yet but learning new things everyday ;) \$\endgroup\$ – loohhoo May 8 at 20:52
  • 1
    \$\begingroup\$ Very nice golfs already, well done! You don't have to count the Action l= in your byte-count, although you do have to count the using System;. Also, if I read the challenge correctly, the newlines are mandatory, instead of those |. So your current answer would be this (coincidentally still 170 bytes). Also note how I've placed parts of the program in the header and footer on TIO, so it's easier to count the byte-count in the code-section (+ the 13 from the using System;). As for some things to golf: \$\endgroup\$ – Kevin Cruijssen May 9 at 11:08
  • 2
    \$\begingroup\$ 121 bytes by switching to the interactive compiler which has implicit usings and can have top-level code outside functions and classes (I also moved the strings' declarations into the first "argument" of for, saving a semicolon): Try it online! \$\endgroup\$ – my pronoun is monicareinstate May 9 at 18:19
6
\$\begingroup\$

Pyth, 44 42 40 38 bytes

Wn30i>5Y2%2>"dzoukno"eaYO2;"ki-yo-shi!

Try it online!

Approach: Repeatedly generate a random number from the set {0, 1} using O2. Store that number in the array Y and use it to index into the string "dzoukno" (which is "zun" and "doko" interleaved). Once the last five elements of Y are [1,1,1,1,0], break the loop and print "ki-yo-shi!".

| improve this answer | |
\$\endgroup\$
5
\$\begingroup\$

K4, 56 48 47 46 bytes

Solution:

{x,1?$`zun`doko}/[75-2/:<-5#;()],,"ki-yo-shi!"

Example:

q)k){x,1?$`zun`doko}/[75-2/:<-5#;()],,"ki-yo-shi!"
"doko"
"zun"
"doko"
"doko"
"doko"
"doko"
"doko"
"doko"
"doko"
"zun"
"zun"
"zun"
"zun"
"zun"
"zun"
"doko"
"ki-yo-shi!"

Explanation:

Generate zun or doko and append to a list whilst the distinct set of the last 5 elements aren't zun zun zun zun doko, and add ki-yo-shi! to the end.

Indices to order zun zun zun zun doko ascending are 4 0 1 2 3. Converted from base-2 yields 75. Other combinations will not yield the same result.

{x,1?$`zun`doko}/[75-2/:<-5#;()],,"ki-yo-shi!" / solution
                                 ,"ki-yo-shi!" / 1-item list of "ki-yo-shi!"
                                ,              / append to
{              }/[          ;  ]               / {function}/[while;starting value]
                             ()                / empty list
                         -5#                   / take last 5 elements
                        <                      / indices to sort ascending
                     2/:                       / convert from base 2
                  75-                          / subtract from 75
     $`zun`doko                                / string ($) -> ("zun";"doko")
   1?                                          / choose (?) 1 item from domain ("zun";"doko")
 x,                                            / append to input

Extra:

  • K (oK) TIO for 47 bytes as we need an extra set of brackets but can drop a colon...
| improve this answer | |
\$\endgroup\$
5
\$\begingroup\$

Python 2, 102 101 97 95 92 91 bytes

-3 bytes thanks to @dingledooper !
Thanks @JhynjhiruuRekrap for reminding that Python source code can include unprintable characters!
Thanks @xnor for saving 1 byte!

import os
s=1
while~s%32:s+=s-(os.urandom(1)>"");print"dzoukno"[~s%2::2]
print"ki-yo-shi!"

Try it online!

Stores the history as bits in the integer s, where 0,1 corresponds to "zun" and "doko". Each time, shift s by 1, then subtract the new bit. Stops when the lowest 5 bits of s are 11111, aka ~s%32 == 0.

Generates a random 0 or 1 by generating a random byte, then checking if the byte is more than 127.

 os.urandom(1)>"{unprintable DEL character}"
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ It seems to me that you could simply replace the tilde with a 7F in a hex editor in your 92-byte solution and that would work. Python 2 still runs it just fine. \$\endgroup\$ – Jhynjhiruu Rekrap May 8 at 22:59
  • 1
    \$\begingroup\$ Also, I don't really want to submit this because it's basically yours, but it can be ported to Python 3 in 97 bytes: import os s=0 p=print while s+2&31:i=os.urandom(1)[0]&1;p("dzoukno"[i::2]);s+=s+i p("ki-yo-shi!") Edit: ugh, newlines are a pain \$\endgroup\$ – Jhynjhiruu Rekrap May 8 at 23:52
  • 1
    \$\begingroup\$ Nice solution! I think I shaved off a byte:TIO. I still wonder if there's bytes to save here. Too bad the "dzoukno"[~s%2::2] has the parity go the wrong way, and s%2*"zun"or"doko" doesn't save a byte because it wastes the space after print in Python 2. Of course the os.urandom part using parens is unfortunate too. \$\endgroup\$ – xnor May 9 at 12:22
  • 1
    \$\begingroup\$ @xnor Wow, the subtracting bit instead of adding is pretty cool. A lot of things are not ideal here unfortunately, but 1 byte is 1 byte :) \$\endgroup\$ – Surculose Sputum May 9 at 15:29
4
\$\begingroup\$

APL (Dyalog Classic), 54 bytes

({⍵⌷'zun' 'doko'}¨⍪∘?∘2⍣{1 1 1 1 2≡¯5↑⍺}⍬)'ki-yo-shi!'

Try it online!

Explanation

({⍵⌷'zun' 'doko'}¨⍪∘?∘2 {1 1 1 1 2≡¯5↑⍺} )'ki-yo-shi!'
                                        ⍬              ⍝ Start with an empty list

                       ⍣                               ⍝ Do this until the condition turns true:
                  ⍪∘?∘2                                ⍝ Append a random number in [1..2]
                        {1 1 1 1 2≡¯5↑⍺}               ⍝ Condition: The list ends in "1 1 1 1 2"

                 ¨                                     ⍝ For every item in this list:
 {⍵⌷'zun' 'doko'}                                      ⍝ 1-Index into the list ['zun','doko']

(                                        )'ki-yo-shi!' ⍝ After that: Append the string 'ki-yo-shi!'
                                                       ⍝ To the end of the output list
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Nice job. You can wrap it in a niladic tradfn wrapper so that you can call it several times to demonstrate non-deterministic output. \$\endgroup\$ – Bubbler May 8 at 5:47
  • \$\begingroup\$ You can use Unicode and count 1 byte per character if you replace bytes with [bytes](https://github.com/abrudz/SBCS). Classic is just for legacy usage, and lacks a few features. \$\endgroup\$ – Bubbler May 8 at 5:54
  • \$\begingroup\$ @Bubbler I don't feel like changing it, because I'm in a hurry to answer other new questions. \$\endgroup\$ – Λ̸̸ May 8 at 6:04
3
\$\begingroup\$

PowerShell, 67 bytes

do{random($a=,'zun'*4+'doko')-ov +o}until("$o"-match$a)'ki-yo-shi!'

Try it online!

Unrolled:

do{
    $array=,'zun'*4+'doko'          # 'zun','zun','zun','zun','doko'
    random $array -OutVariable +out # choose one element from the array randomly. 'doko' may appear in 20% of cases. it's still random.
                                    # output a result to the output channel (console by default) AND to the variable $out.
                                    # '+out' means adding to $out instead of replacing of $out
                                    # see https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_commonparameters
}until("$out" -match $array)        # powershell casts the $array to a string implicitly
'ki-yo-shi!'
| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

Retina, 50 bytes

/(n¶.+){4}o$/^+?(`\z
zun¶
)`\z
doko¶
\z
ki-yo-shi!

Try it online! Explanation:

/(n¶.+){4}o$/^+

Repeat until the buffer ends with 4 lines ending with n and a line ending in o. Note that the $ anchor works like \Z or ¶?\z, so I don't need to match the trailing newline explicitly.

?(`
)`

Execute one of the inner stages chosen randomly.

\z
zun¶
\z
doko¶

Append either zun or doko. Note that I can't use $ here as I only want to match the very end and the $ would match before the final newline as well as after it.

\z
ki-yo-shi!

Finally append ki-yo-shi!.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ @mathjunkie Looks like I'm not the only one... thanks! \$\endgroup\$ – Neil May 8 at 14:29
3
\$\begingroup\$

My first attempt at a golf, and using a language not remotely suited for golfing, no less! I can't think of any ways to shrink this because Lua is a verbose, spacey language. But I still love her anyways.

I should give a heads-up: when the Lua interpreter starts, its pRNG seed seems to always default to the same value (rather than polling /dev/random or something), so running it once will always provide the same result. TIO, therefore, creates the same output repeatedly. This will change when 5.4 is released.

Credits to manatwork for a 22% reduction over four changes.

Lua, 132 123 107 104 103 bytes

z=0repeat if math.random(2)<2then print"zun"z=z+1 else w=z>3z=0print"doko"end until w print"ki-yo-shi!"

Try it online!

Explanation, because why not?

z=0                           --set a variable to count consecutive "zun"s
repeat                        --loop until we hit the target circumstance
    if math.random(2)<2 then  --pick 1 or 2: 1 = "zun", 2 = "doko"
        print"zun"            --print "zun"
        z=z+1                 --increment the "zun" counter
    else                      --when the pRNG lands 2
        w=z>3                 --after 4 consecutive "zun"s, w will be false
        z=0                   --reset the counter
        print"doko"           --print doko
    end
until w                       --loop kills when w is defined (as true)
                              --execution only gets here if we succeed...
print"ki-yo-shi!"             --...so print "ki-yo-shi!" and halt
| improve this answer | |
\$\endgroup\$
  • 3
    \$\begingroup\$ in Lua only false and nil are falsy values, so replace true with a single digit number. As there will be no execution beyond ==4, just make it >3. For the same reason resetting z doesn't need to be in the else block, can be anywhere after the then block's end. Try it online! \$\endgroup\$ – manatwork May 10 at 3:15
  • \$\begingroup\$ Can't believe I forgot about truthiness, as that's one of my favorite parts of the language. Thanks! \$\endgroup\$ – wundrweapon May 10 at 3:20
  • \$\begingroup\$ The if only for that single break is too long. Better save the z>3 condition's result in a variable and use it to control the loop. Try it online! \$\endgroup\$ – manatwork May 10 at 3:34
  • \$\begingroup\$ Add another twist to my previous suggestion and use a repeat .. until loop, so the loop control variable doesn't have to be initialized before the loop. Try it online! \$\endgroup\$ – manatwork May 10 at 3:46
  • \$\begingroup\$ I was just starting to think a repeat-until loop would be smarter, but you beat me to it \$\endgroup\$ – wundrweapon May 10 at 3:47
3
\$\begingroup\$

Ruby, 71...59 57 bytes

-4 bytes thanks to @ValueInk!

$/+=p %w[zun doko].sample until$/=~/n.{9}d/;p'ki-yo-shi!'

Try it online!

Stores output history by appending zun or doko to the string $/ (the predefined input record separator). Halts when the string contains an n, followed by exactly 9 characters, followed by a d. This can only occur when the string ends with zunzunzunzundoko.

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Python 2, 94 bytes

from random import*
s=""
while"zo">s[-21::19]:s+=choice(["zun,","doko,"])
print s+"ki-yo-shi!"

Try it online!

This is an improvement based on an older version of Surculose Sputum's answer.

The idea is to identify the ending sequence in the comma-separated string by checking that the 21st and 2nd characters from the end are z and o respectively.

...,zun,zun,zun,zun,doko,
    ^                  ^
    z                  o

This is the only ending that satisfies this. To get a z in the 21st-to-last position, the last five words must be exactly four zun, and one doko,, since their lengths of 4 and 5 can add up to 21 only as 4*4+5. Then, the one doko, must be at the end to get o in the second-to-last position. Moreover, because zo is the largest string that could be made here, we can check inequality with < rather than !=, saving a byte.

It would be shorter to use urandom similarly to Surculose Sputum's new answer.

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Julia 1.0, 92 bytes

A simple recursive implementation. i keeps track of how often "zun" has occured.

f(i=0)=(r=rand(1:2);println([:zun,:doko][r]);r>1 ? i>3 ? print("ki-yo-shi!") : f() : f(i+1))

Try it online!

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Java 10, 148 141 137 136 125 123 112 110 107 bytes

v->{var r="";for(int k=3;k!=1;r+=k%2<1?"zun/":"doko/")k=k<<7^(int)(Math.random()*2);return r+"ki-yo-shi!";}

Golfed version of the approach that @loohhoo used in her C# answer.
-4 bytes thanks to @ceilingcat.
An additional -11 bytes from @loohhoo's new approach (after I helped her golf it a bit), so make sure to upvote her if you haven't already!
-11 bytes by porting @Arnauld's JavaScript answer (thanks to @OlivierGrégoire)
And yet another -3 bytes thanks to @loohhoo's third new approach, haha ;D

Uses / instead of newlines as delimiter.

Try it online.

Explanation:

v->{                      // Method with empty unused parameter and String return-type
  var r="";               //  Result-String, starting empty
  for(int k=3;            //  Bit-mask integer
      k!=1;               //  Loop as long as `k` is not 1 yet:
      ;                   //    After every iteration:
       r+=k%2<1?          //     If `k` is even:
           "zun/"         //      Append "zun" and a "/" to the result
          :               //     Else (`k` is odd):
           "doko/")       //      Append "doko" and a "/" to the result
    k=                    //    Change `k` to:
      k<<7                //     First bit-wise left-shift it by 7
      ^(int)(Math.random()*2);
                          //     And then bitwise-XOR it with a random 0 or 1
  return r                //  Return the result-String
          +"ki-yo-shi!";} //  appended with "ki-yo-shi!"
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ For some reason I used doku instead of doko in my answer... I'm arbitrarily blaming you. \$\endgroup\$ – Neil May 9 at 19:51
  • \$\begingroup\$ @Neil Lol, not sure how I misread that, but thanks for noticing I guess. ;) \$\endgroup\$ – Kevin Cruijssen May 9 at 20:48
  • 1
    \$\begingroup\$ 112 bytes, by porting Arnauld's answer. \$\endgroup\$ – Olivier Grégoire May 11 at 9:50
  • 1
    \$\begingroup\$ @OlivierGrégoire Thanks. And another -2 by only doing j=2 once. :) \$\endgroup\$ – Kevin Cruijssen May 11 at 10:16
  • \$\begingroup\$ Good catch! :-) \$\endgroup\$ – Olivier Grégoire May 11 at 10:21
1
\$\begingroup\$

Raku, 61 bytes

(<doko zun>[{^2 .pick}...{:2[@_]%32==30}],'ki-yo-shi!')».say

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

C (gcc), 104 \$\cdots\$ 96 91 bytes

Saved 2 bytes thanks to Arnauld!!!

Saved a byte thanks to tsh!!!

Saved 5 bytes thanks to ceilingcat!!!

f(m){srand(time(0));for(m=3;m%32-1;m+=m+puts(rand()%2?"doko":"zun")-4);puts("ki-yo-shi!");}

Try it online!

How

\$m\$ stores a history of what's randomly been printed over time in its bits, the least-significant bit storing the most recent. A bit in \$m\$ at time \$t\$ is set to:

$$ m_t = \left\{ \begin{array}{ll} 0 & \text{zun} \\ 1 & \text{doko} \end{array} \right. $$ When the binary pattern \$00001_2\$ occurs in the least-significant \$5\$ bits of \$m\$ the sequence \$(\text{zun}, \text{zun}, \text{zun}, \text{zun}, \text{doko})\$ has just appeared. \$m\$ is initialised to \$11_2\$ so, at the beginning, it appears as though \$(\text{doko},\text{doko})\$ has just occurred forcing at least \$5\$ spins before \$00001_2\$ can occur.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ (m&31) can be replaced with m%32 \$\endgroup\$ – Arnauld May 8 at 8:37
  • \$\begingroup\$ @Arnauld A simple but very interesting golf: \$\mod{2^n}\$ is the same as masking the \$n\$ least-significant bits - thanks! :-) \$\endgroup\$ – Noodle9 May 8 at 8:48
  • 1
    \$\begingroup\$ What about m;r;f() -> f(m,r)? \$\endgroup\$ – tsh May 8 at 10:27
  • \$\begingroup\$ @tsh Nice one - thanks! :-) \$\endgroup\$ – Noodle9 May 8 at 11:29
  • \$\begingroup\$ @ceilingcat Very nice - thanks! :-) \$\endgroup\$ – Noodle9 May 8 at 18:28
1
\$\begingroup\$

Charcoal, 38 bytes

W›⁴⌕✂υ±⁵Lυ¹doko⊞υ‽⪪dokozun⁴υki-yo-shi!

Try it online! Link is to verbose version of code. Explanation:

W›⁴⌕✂υ±⁵Lυ¹doko

Repeat until the string doko is the last of the last 5 strings in the initially empty list (thus the first four must all be zun)...

⊞υ‽⪪dokozun⁴

... split the string dokozun into substrings of length at most 4 and push one randomly to the list.

υki-yo-shi!

Output the list and ki-yo-shi!. (Charcoal automatically outputs each list element on its own line.)

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Wolfram Language, 109 bytes

Join[NestWhile[#~Join~{RandomChoice@{z,d}}&,{},#[[-5;;]]=!={z,z,z,z,d}&]/.z->"zun"/.d->"doko",{"ki-yo-shi!"}]

Try it online!

Pretty straightforward: randomly appends z or d to a list until the last five elements match {z,z,z,z,d}, converts each to the proper string, then appends "ki-yo-shi!".

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

R 161 143 69 bytes

An initial & fairly clumsy attempt at a code golf challenge involving text!, and defining

b=c("doko","zun")

as a header.

for(i in -3:which(apply(matrix((a<-sample(0:1,2e5,r=T))[outer(1:5,1:1e5,"+")],5)*2^(0:4),2,sum)==15)[1])cat(b[1+a[i+5]],"\n") cat("ki-yo-shi!")

Try it online!

Using the original Japanese characters with

b=c("ドコ","ズン")

and

cat("キヨシ!")

brings the score down to 137 bytes...

A better alternative to using cat( would be appreciated as the ,"\n" part wastes 5 bytes for a newline command.

A different approach reducing the count

e=0
while(e<1){x=rt(1,1)<0)
cat(b[1+x],"\n")
e=e*x-x+(!x&-3>e)}
cat(a)

when adding

a="ki-yo-shi!"

to the header.

Try it online!

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.