32
\$\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\$
7
  • 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\$ May 8, 2020 at 3:02
  • \$\begingroup\$ "your output has to be non-deterministic" - does employing pseudo-random numbers count as being non-deterministic? \$\endgroup\$
    – user92069
    May 8, 2020 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, 2020 at 3:27
  • \$\begingroup\$ @Λ̸̸ Yes, unless you use the exact same seed for the PRNG every time. \$\endgroup\$
    – sporeball
    May 8, 2020 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, 2020 at 6:15

28 Answers 28

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.

\$\endgroup\$
1
  • \$\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, 2020 at 18:24
8
\$\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.

\$\endgroup\$
5
  • 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\$ May 8, 2020 at 9:03
  • \$\begingroup\$ @KevinCruijssen wow, I don't know how I missed that. Thanks! \$\endgroup\$
    – lyxal
    May 8, 2020 at 9:08
  • 1
    \$\begingroup\$ Oh, and another -2 by changing ¯5.£J30bQ to ¯J30bÅ¿. :) (PS: My name isn't Keven ;p) \$\endgroup\$ May 8, 2020 at 9:09
  • 1
    \$\begingroup\$ @KevinCruijssen aw h*ck. Sorry about that! \$\endgroup\$
    – lyxal
    May 8, 2020 at 9:13
  • \$\begingroup\$ Np, it isn't the first time my name is misspelled like that, haha ;) \$\endgroup\$ May 8, 2020 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.

\$\endgroup\$
11
  • 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\$ May 8, 2020 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\$ May 8, 2020 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, 2020 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\$ May 9, 2020 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\$ May 9, 2020 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!".

\$\endgroup\$
6
\$\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...
\$\endgroup\$
1
  • \$\begingroup\$ You can get the best of both worlds (dropping a : but without adding ()) by using ngn/k \$\endgroup\$
    – coltim
    Feb 12, 2021 at 17:48
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}"
\$\endgroup\$
4
  • 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\$ May 8, 2020 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\$ May 8, 2020 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, 2020 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\$ May 9, 2020 at 15:29
4
\$\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
\$\endgroup\$
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
\$\endgroup\$
3
  • \$\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, 2020 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, 2020 at 5:54
  • \$\begingroup\$ @Bubbler I don't feel like changing it, because I'm in a hurry to answer other new questions. \$\endgroup\$
    – user92069
    May 8, 2020 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!'
\$\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!.

\$\endgroup\$
0
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
\$\endgroup\$
6
  • 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, 2020 at 3:15
  • \$\begingroup\$ Can't believe I forgot about truthiness, as that's one of my favorite parts of the language. Thanks! \$\endgroup\$ May 10, 2020 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, 2020 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, 2020 at 3:46
  • \$\begingroup\$ I was just starting to think a repeat-until loop would be smarter, but you beat me to it \$\endgroup\$ May 10, 2020 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.

\$\endgroup\$
2
2
\$\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.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ (m&31) can be replaced with m%32 \$\endgroup\$
    – Arnauld
    May 8, 2020 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, 2020 at 8:48
  • 1
    \$\begingroup\$ What about m;r;f() -> f(m,r)? \$\endgroup\$
    – tsh
    May 8, 2020 at 10:27
  • \$\begingroup\$ @tsh Nice one - thanks! :-) \$\endgroup\$
    – Noodle9
    May 8, 2020 at 11:29
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.

\$\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!

\$\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!"
\$\endgroup\$
6
  • \$\begingroup\$ For some reason I used doku instead of doko in my answer... I'm arbitrarily blaming you. \$\endgroup\$
    – Neil
    May 9, 2020 at 19:51
  • \$\begingroup\$ @Neil Lol, not sure how I misread that, but thanks for noticing I guess. ;) \$\endgroup\$ May 9, 2020 at 20:48
  • 1
    \$\begingroup\$ 112 bytes, by porting Arnauld's answer. \$\endgroup\$ May 11, 2020 at 9:50
  • 1
    \$\begingroup\$ @OlivierGrégoire Thanks. And another -2 by only doing j=2 once. :) \$\endgroup\$ May 11, 2020 at 10:16
  • \$\begingroup\$ Good catch! :-) \$\endgroup\$ May 11, 2020 at 10:21
2
\$\begingroup\$

Zsh, 83 bytes

>zun>doko
49744()<<<ki-yo-shi!>>*
*(){`sum<<<$@`||$@ `ls|shuf -n1|tee -a *`}
z* * *

Try it online!

Outputs to the files named zun and doko (both should be identical).

  • >zun>doko - create the files zun and doko
  • 49744() - define a function called 49744
    • <<<ki-yo-shi! - output ki-yo-shi!
    • >>* - append to all files
  • *(){} - define a function with the names of all the files in the current directory (i.e. zun and doko)
    • sum<<<$@ - take the checksum of the arguments
    • `` - try to execute that as a command
      • the checksum of zun zun zun doko is 49744, which is defined as a command. All other combinations are not.
    • || - if that fails (i.e. the arguments are not zun zun zun doko):
      • ls - list all files in the current directory
      • shuf -n1 - pick one item at random
      • tee -a * - append to all the files in the current directory, as well as being captured by the ``
      • `` - then pass that as the last argument to:
        • $@ - execute the arguments: the first argument is the command to execute, the remaining ones are passed as arguments. Since the first argument is always either zun or doko, this actually recurses, passing all but the first argument, with the new random string appended.
  • z* * * - initial recursive call - call the function with the name "all files that start with z" (i.e. zun),
    • * * - with the arguments "all files" and "all files" (i.e. doko zun doko zun)
\$\endgroup\$
1
  • \$\begingroup\$ -1: actually I sometimes get bad outputs such as "zun zun doko ki-yo-shi!" "zun zun zun doko ki-yo-shi!". You have to end with "zun zun zun zun doko ki-yo-shi!". \$\endgroup\$
    – user100411
    Jun 13, 2021 at 9:51
2
\$\begingroup\$

VBScript, 257 bytes

Randomize():z="zun,":d="doko,":Do:a=a&Array(z,d)(Round(Rnd())):Loop While UBound(Split(a,","))<5:Do:a=Split(a,","):a(0)="a":a=Replace(Join(a,",")&Array(z,d)(Round(Rnd())),"a,",e):MsgBox a:Loop While Not Cbool(Instr(a,"zun,zun,zun,doko,")):MsgBox"ki-yo-shi!"
\$\endgroup\$
5
  • \$\begingroup\$ Hi, welcome to PPCG! Do you mind adding a header to that like the other answers? It goes like # Language, N bytes. \$\endgroup\$
    – EasyasPi
    Jun 19, 2021 at 15:55
  • \$\begingroup\$ @EasyasPi fixed it! Sorry! \$\endgroup\$ Jun 19, 2021 at 17:01
  • \$\begingroup\$ Does this actually output "zun" and "doko"? \$\endgroup\$
    – EasyasPi
    Jun 19, 2021 at 21:57
  • \$\begingroup\$ @EasyasPi it doesn't, every x is either 0 ("zun") or 1 ("doko"), I'll fix that and repost with the actual number of bytes! \$\endgroup\$ Jun 19, 2021 at 22:48
  • 1
    \$\begingroup\$ @EasyasPi Fixed the script, now it outputs 'zun' and 'doko'! :) \$\endgroup\$ Jun 19, 2021 at 23:10
1
\$\begingroup\$

Raku, 61 bytes

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

Try it online!

\$\endgroup\$
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.)

\$\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!".

\$\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!

\$\endgroup\$
1
\$\begingroup\$

ThumbGolf, 53 bytes

Machine code (little endian pairs):

2100 de78 0840 bf2c a008 a009 4149 de00
de3a f001 011f 291e d1f3 a001 de00 4770
696b 792d 2d6f 6873 2169 000a 757a 006e
6f64 6f6b 00

Commented assembly:

        // Include ThumbGolf wrapper macros
        .include "thumbgolf.inc"
        .globl main
        .thumb_func
main:
        // Set our counter bitmask to zero
        movs    r1, #0
.Lloop:
        // Store a 32-bit random integer into r0.
        rand    r0
        // Using lsrs, test the lowest bit.
        lsrs    r0, r0, #1
        // Set up an IT block, checking the carry flag set from lsrs
        ite     cs
          // If the lowest bit was 1, set r0 to "zun"
          adrcs r0, .Lzun
          // Otherwise, set it to "doko"
          adrcc r0, .Ldoko
        // Add to the bitmask using adcs.
        // r1 = r1 * 2 + (rand() & 1)
        adcs    r1, r1
        // Print the string in r0
        puts    r0
        // Print a newline. We could technically put the newline in the strings
        // themselves for a THEORETICALLY identical byte count, but the true
        // reason for this (and the main reason I added this instruction) is to
        // make it so the string literals are aligned, preventing wide ADR.
        putspc  '\n'
        // Mask the lowest 5 bits using wide AND
        and     r1, r1, #0b11111
        // 0b11110 means zun zun zun zun doko, loop while it is not that
        cmp     r1, #0b11110
        bne     .Lloop
.Lloop.end:
        // Print "ki-yo-shi!"
        adr     r0, .Lkiyoshi
        puts    r0
        // Return
        bx      lr
        // These string literals are very carefully placed so that they are
        // all 4 byte aligned. That is the only reason for the trailing newline:
        // it makes kiyoshi an even multiple of 4 bytes.
.Lkiyoshi:
        .asciz "ki-yo-shi!\n"   // 12 bytes (aligned)
.Lzun:
        .asciz "zun"            // 4 bytes (aligned)
.Ldoko:
        .asciz "doko"           // 5 bytes (aligned)

Output is to stdout.

It wasn't easy figuring out how to align my string literals, but it was definitely worth it.

Note that I created ThumbGolf after this question was submitted.

\$\endgroup\$
1
\$\begingroup\$

Pxem, 66 bytes (filename).

Unprintables are as a backslash followed by its code point in three-digit octal.

\001.t.z\002.r.wzun.p.m\001.+.t\001o.r.ao.zdok.p.m\004.xki-yo-shi!.p.d.a\001.tXX.a.a

With comments

XX.z
# heap: 1 as counter
.a\001.t.zXX.z
  # choosing either zun or doko
  .a\002.r.wXX.z
    .azun.pXX.z
    # increment counter
    .a.m\001.+.tXX.z
    # push o for next dot-z and get out
    .a\001o.r.aXX.z
  # if empty; then push o and get in
  # else pop it and ignore next block
  .ao.zXX.z
    # reusing the o
    .adok.pXX.z
    # print kiyoshi and exit if counter is >4
    .a.m\004.xki-yo-shi!.p.d.aXX.z
    # else reset counter to 1
    .a\001.tXX.aXX.z
# pop a garbage of an o if any
.a.a

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Ly, 96 bytes

"ki-oy-shi!">"okod">"nuz">666661[p09?5Gfps[p<0]p<0&:p[o](10)opl[p>0]p>l:rp&s&+lr2=fp*[<<<&o;]p1]

Try it online!

This code uses 4 stacks, one for each of the output lines, and one holding 0|1 indicators of the last 4 output choices (picked using random numbers). Then it writes the ki-oy-shi! line and exits if the sum of the choices (and last choice) show that the exit pattern was generated.

"ki-oy-shi!">"okod">"nuz">       # Push the strings onto separate stacks
66666                            # Initialize the stack to a "not done" state
1[p    ...code...    1]          # An infinite loop pattern
09?5Gfp                          # Pushes 0|1 on the stack randomly
       s                         # Save the choice on the backup stack
        [p<0]p<                  # Shift 1 or 2 stacks, depending on random choice
               0&:p              # Duplicate the stack with a 0 sep, pop the top 0
                   [o](10)op     # Print one copy of the stack, plus LF, pop the 0
l[p>0]p>                         # Restore random choice, shift back 1 or 2 stacks
        l:                       # Restore random choice, duplicate it on stack
          rp                     # Reverse the stack, delete top (remove oldest choice)
            &s&+l                # Save stack, sum the choices, restore stack
                 r2=fp           # Reverse stack to move sum on top, compare to 2
                      *          # Combine with latest choice, if 1 we are done
                       [<<<&o;]  # Time to go, switch stacks, print and exit 
                               p # Delete the test results from the stack, then loop...
\$\endgroup\$
1
\$\begingroup\$

Vyxal o, 36 bytes

{₀℅:£J:5NȯB30≠«ǎ⌈8τ«½¥i,|}`ki-yo-∪Ǎ!

Try it Online!

-7 thanks to lyxal.

\$\endgroup\$
2
0
\$\begingroup\$

APL (Dyalog Unicode), 51 bytes

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

Try it online!

Slight improvement on the other solution, since the account is deleted.

\$\endgroup\$
0
\$\begingroup\$

Knight, 54 bytes

;=aF;W-30;O I=x%R2"zun""doko"=a%+x*2a 32xO"ki-yo-shi!"

Try it online!

Uses the bitmask setup.

# Initialize with FALSE. We will coerce it to
# Number later, just get some form of 0.
; = mask FALSE
# loop while mask != 30
; WHILE( - 30
          # chaining ftw
          ; OUTPUT 
             : IF (= x % RAND 2){"zun"}{"doko"}
          # mask = ((mask << 1) | x) % 32
          : = mask % (+ x (* 2 mask)) 32
        ) {
    : NOP # we use "x" in the golfed code.
}
: OUTPUT "ki-yo-shi!"
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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