49
\$\begingroup\$

Former US Secretary of Defense, Donald Rumsfeld, famously popularized the phrase "known knowns." Here we're going to distill his remarks into a four-line stanza.

Specifically, output this text:

known knowns
known unknowns
unknown knowns
unknown unknowns

Capitalization doesn't matter (for example, Known unKnowns is fine), and a single trailing newline is acceptable, but no other formatting changes are allowed. That means a single space between the words, and either LF (59 bytes) or CR/LF (62 bytes) between the lines.

Rules

  • Either a full program or a function are acceptable. If a function, you can return the output rather than printing it.
  • Standard loopholes are forbidden.
  • This is so all usual golfing rules apply, and the shortest code (in bytes) wins.
\$\endgroup\$
8
  • 1
    \$\begingroup\$ Can anyone explain why this has got so many downvotes? For me it is a reasonable challenge and has encouraged a variety of answers in a mixture of languages. \$\endgroup\$
    – ElPedro
    Commented Oct 16, 2017 at 19:04
  • 49
    \$\begingroup\$ @ElPedro The reason behind the many downvotes is a known unknown \$\endgroup\$ Commented Oct 16, 2017 at 21:18
  • \$\begingroup\$ May we return a matrix or a list of strings? \$\endgroup\$
    – Adám
    Commented Oct 17, 2017 at 7:57
  • 1
    \$\begingroup\$ @Adám A list of four strings would be OK, as that's still preserving the space between words; but, unless you're doing a matrix of every character including the spaces, matrices are not OK. \$\endgroup\$ Commented Oct 17, 2017 at 12:21
  • 1
    \$\begingroup\$ Are the trailing spaces intentional? \$\endgroup\$
    – user202729
    Commented Dec 25, 2017 at 15:16

62 Answers 62

30
\$\begingroup\$

Python 2, 54 52 bytes

-2 bytes thanks to xnor

k='unknowns'
for i in 8,6,2,0:print k[i/3:7],k[i%3:]

Try it online!

The results from the / and % will be [[2, 2], [2, 0], [0, 2], [0, 0]] that will be the starting indexes, removing the un when 2, keeping the string unaltered when 0

\$\endgroup\$
1
  • 1
    \$\begingroup\$ If you let k be 'unknowns', you can correct with k[i/3:7] and save two bytes. \$\endgroup\$
    – xnor
    Commented Oct 16, 2017 at 18:50
28
\$\begingroup\$

Vim 28 25 bytes

This is my first Vim answer, any golfing tips are welcome.

2iunknown ␛rsY3P2xw.+.jw.

In action

Thank you Lynn for writing the python script to make that fantastic animation.

This can also be run by V Try it Online!

Also 25:

2iknown ␛rsY3pwiun␛+.+.w.
\$\endgroup\$
2
  • \$\begingroup\$ I only managed to find another 25: 2iunknown ␛rsYPw2x2YP2xj. or a slight variation 2iunknown ␛rsYPw2x2YPⓋjlx (Ⓥ = Ctrl-V). \$\endgroup\$
    – lynn
    Commented Oct 18, 2017 at 12:09
  • \$\begingroup\$ @Lynn Nice, I tried Ctrl-V but got something longer. \$\endgroup\$
    – H.PWiz
    Commented Oct 18, 2017 at 12:20
23
\$\begingroup\$

bash, 36 bytes

printf %s\\n {,un}known\ {,un}knowns

other solutions

36

eval echo\ {,un}known\ {,un}knowns\;

37

eval printf '%s\\n' \{,un}known{\\,s}

38

eval eval echo\\ \{,un}known{\\,'s\;'}

41

x=\\\ {,un}known;eval "eval echo$x$x\s\;"

45

x='\ {,un}known' e=eval;$e "$e echo$x$x\s\;"
x='\ {,un}known' e=eval\ ;$e"$e\echo$x$x\s\;"

if leading newline and extra space were accepted 31 bytes :

echo '
'{,un}known\ {,un}knowns
\$\endgroup\$
4
  • 3
    \$\begingroup\$ for those wondering what kind of sorcery is this (like myself): this is bash brace expansion \$\endgroup\$
    – bolov
    Commented Oct 17, 2017 at 14:36
  • \$\begingroup\$ … even better explained on bash-hackers.org, and you can Try it online!. \$\endgroup\$
    – dessert
    Commented Oct 18, 2017 at 13:17
  • \$\begingroup\$ If in doubt, put the whole answer in a code block \$\endgroup\$
    – Stan Strum
    Commented Oct 26, 2017 at 22:42
  • \$\begingroup\$ reworded, the invalid input at the end \$\endgroup\$ Commented Oct 27, 2017 at 7:28
14
\$\begingroup\$

05AB1E, 13 12 bytes

Saved 1 byte thanks to Erik the Outgolfer (avoid closing string)

„Š¢—‚#D's«â»

Try it online!

Explanation

„Š¢—‚           # push the string "known unknown"
     #          # split on spaces
      D         # duplicate
       's«      # append "s" to each
          â     # cartesian product
           »    # join on newline
\$\endgroup\$
3
  • 2
    \$\begingroup\$ “Š¢—‚“ -> „Š¢—‚ \$\endgroup\$ Commented Oct 16, 2017 at 13:34
  • \$\begingroup\$ @EriktheOutgolfer: Oh yeah, only 2 words. Thanks! \$\endgroup\$
    – Emigna
    Commented Oct 16, 2017 at 13:34
  • \$\begingroup\$ Bahhh... why didn't I look first? Same answer. \$\endgroup\$ Commented May 1, 2018 at 0:14
11
\$\begingroup\$

CJam (26 25 bytes)

"unknown"_2>\]2m*{S*'sN}%

Online demo

Cartesian product of ["known" "unknown"] with itself, then each element joined with space and suffixed with s and a newline.

Thanks to Erik for a one-byte saving.

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

R, 52 51 50 bytes

cat(gsub(1,"known","1 1s
1 un1s
un1 1s
un1 un1s"))

Try it online!

Surprisingly short substitution and print commands make this an actually competitive R answer in a challenge!

Even if it's super boring. Mildly more interesting now, and with a byte saved thanks to J.Doe!

Saved another byte thanks to this answer, also by J.Doe!

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

Shakespeare Programming Language, 1021 1012 993 bytes

-19 bytes thanks to Joe King!

,.Ajax,.Ford,.Page,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:Am I nicer a big cat?If sois the remainder of the quotient betweenI the sum ofa cat a big cat worse a big cat?If notlet usScene V.You be the sum ofa fat fat fat pig the cube ofthe sum ofa cat a big big cat.Speak thy.You be the sum ofyou the sum ofa cat a fat fat fat pig.Speak thy.Scene V:.[Exit Ajax][Enter Page]Page:You be the product ofthe sum ofa cat a big big cat the sum ofa pig a big big big big cat.Speak thy.You be the sum ofyou the sum ofa cat a big cat.Speak thy.Ford:You be the sum ofI a cat.Speak thy.You be the sum ofyou a big big big cat.Speak thy.Page:Speak thy.You be the sum ofyou the sum ofa cat a big big cat.Is the remainder of the quotient betweenAjax a big cat worse a cat?If soyou big big big big big cat.Speak thy.If solet usScene X.You be twice the sum ofa cat a big big cat.Speak thy.Scene X:.[Exit Page][Enter Ajax]Ford:You be the sum ofyou a cat.Be you worse a big big big cat?If solet usAct I.

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ You cam remove the spaces after some multi-word operators like the sum of \$\endgroup\$
    – Jo King
    Commented Sep 9, 2018 at 23:43
  • \$\begingroup\$ Really? Huh, that's a lot of shortest-representations-of-numbers I have to recalculate. Thanks. \$\endgroup\$ Commented Sep 10, 2018 at 0:17
6
\$\begingroup\$

Haskell, 60 58 53 51 bytes

f<$>l<*>l
f x y=x++' ':y++"s"
l=["known","unknown"]

Try it online!

Yields a list of lines as was recently allowed. Thanks to @firefrorefiddle for pointing out.

-2 bytes thanks to cole.


58 byte version:

f=<<"? ?s\n? un?s\nun? ?s\nun? un?s"
f '?'="known"
f c=[c]

Try it online! Yields a single string.

\$\endgroup\$
2
  • \$\begingroup\$ Your 60 byte version is actually a 53 byte version because you can remove unlines because "A list of four strings would be OK, as that's still preserving the space between words;" (Comment to original question). \$\endgroup\$ Commented Oct 18, 2017 at 10:34
  • 1
    \$\begingroup\$ 51 bytes combining your approach with @PeterTaylor's \$\endgroup\$
    – cole
    Commented Jul 29, 2019 at 21:13
5
\$\begingroup\$

C# (.NET Core), 54 bytes

v=>@"z zs
z unzs
unz zs
unz unzs".Replace("z","known")

Try it online!

\$\endgroup\$
5
\$\begingroup\$

Retina, 33 32 bytes


 s¶ uns¶un s¶un uns
 |s
known$&

Try it online! Edit: Saved 1 byte thanks to @ovs. Explanation: This is almost the trivial approach of using a placeholder for known, except here I simply insert it before each space or s, which saves 3 4 bytes.

\$\endgroup\$
3
5
\$\begingroup\$

PHP, 55 51 47 bytes

<?=strtr("1 1s
1 01s
01 1s
01 01s",[un,known]);

try it online

\$\endgroup\$
2
  • \$\begingroup\$ Do you need opening tags for php entries? \$\endgroup\$
    – Josiah
    Commented Oct 18, 2017 at 19:13
  • \$\begingroup\$ @Josiah I need something to print the result; <?= is the shortest option. \$\endgroup\$
    – Titus
    Commented Oct 19, 2017 at 11:08
5
\$\begingroup\$

Retina, 33 32 bytes

Saved 1 byte using an intermediate printing approach from Leo.


 ¶u

knowns
u
 un
:`s 
 
m`^
un

Try it online!

Explanation


 ¶u

Turns the non-existent (i.e. empty) input into the string on the second line. That one seems pretty weird, but these characters are codes for the stuff that goes between two instances of known[s] on the first two lines of the result. Space and linefeed are just themselves and u is un.


knowns

Now we insert knowns at every position (i.e. at the beginning, end, and between every pair of characters).

u
 un

We decode the u.

:s 
 

Then we get rid of the ss in front of spaces, i.e. those in the first half of each line, and print the result.

m`^
un

And finally we prepend un to both lines and print the result again.

This beats the trivial approach of just using a placeholder for known by 4 bytes, but not Neil's more efficient implementation of that approach.

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

C (gcc),  79  78 76 bytes

Thanks to @Justin Mariner for golfing one byte!

f(){printf("%s %1$ss\n%1$s un%1$ss\nun%1$s %1$ss\nun%1$s un%1$ss","known");}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ I think this can be one byte less if you use %1$s and get rid of i: Try it online! \$\endgroup\$ Commented Oct 16, 2017 at 15:59
4
\$\begingroup\$

Perl 6, 45 bytes

$_='known';.say for [X](($_,"un$_")xx 2)X~'s'

Try it

Expanded

$_ = 'known';

.say                # print with trailing newline the value in topic variable 「$_」

  for               # do that for each of the following

    [X](
      ($_, "un$_")  # ('known','unknown')
        xx 2        # list repeated twice
    ) X~ 's'        # cross using &infix:«~» with 's' (adds 「s」 to the end)

The [X](…) part generates

(("known","known"),("known","unknown"),("unknown","known"),("unknown","unknown")).Seq

Then using X~ on it coerces the inner lists into a Str (because of the &infix:«~» operator), which doing so adds a space between values.

("known known", "known unknown", "unknown known", "unknown unknown").Seq

Then each is joined with an s

("known knowns", "known unknowns", "unknown knowns", "unknown unknowns").Seq
\$\endgroup\$
1
  • \$\begingroup\$ 41 bytes \$\endgroup\$
    – Jo King
    Commented Sep 9, 2018 at 16:11
4
\$\begingroup\$

Haskell, 57 52 bytes

id=<<id=<<mapM(\s->[s,"un"++s])["known ","knowns\n"]

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ 49 bytes with an alternate output of list \$\endgroup\$
    – cole
    Commented Jul 29, 2019 at 21:23
  • \$\begingroup\$ @cole: the output format is very strict, so I think a list of strings in not valid. \$\endgroup\$
    – nimi
    Commented Jul 29, 2019 at 22:10
  • \$\begingroup\$ the other haskell answer does it, seems like the OP okayed that format. \$\endgroup\$
    – cole
    Commented Jul 29, 2019 at 23:28
4
\$\begingroup\$

APL (Dyalog), 64 47 35 bytes

⍪,∘.{⍺,' ',⍵,'s'}⍨k('un',k←'known')

Try it online!

How?

k←'known' - k is "known"

k('un',k←'known') - "known" "unknown"

∘.... - outer product with itself

    {⍺,' ',⍵,'s'} - with the function that formats the args as {⍺} {⍵}s

, - smash the product table into vector

- separate to columns

\$\endgroup\$
2
  • \$\begingroup\$ 33 bytes (+ fixing the bad output format) \$\endgroup\$
    – dzaima
    Commented Sep 9, 2018 at 17:46
  • 1
    \$\begingroup\$ @dzaima 31 \$\endgroup\$
    – user41805
    Commented Sep 10, 2018 at 9:09
4
\$\begingroup\$

Java 8, 56 55 bytes

v->" s\n uns\nun s\nun uns".replaceAll(" |s","known$0")

-1 byte thanks to @SuperChafouin.

Explanation:

Try it here.

v->                         // Method with empty unused parameter
  " s\n uns\nun s\nun uns"  //  Literal String
   .replaceAll(" |s",       //  Replace all spaces and "s" with:
     "known                 //   Literal "known"
           $0")             //   + the match (the space or "s")
                            // End of method (implicit / single-line return-statement)
\$\endgroup\$
3
  • \$\begingroup\$ Okay, I gotta ask... why \r? ^^' \$\endgroup\$ Commented Oct 16, 2017 at 14:32
  • \$\begingroup\$ @OlivierGrégoire Woops.. ;p \$\endgroup\$ Commented Oct 16, 2017 at 14:52
  • 1
    \$\begingroup\$ You can win one byte with v->" s\n uns\nun s\nun uns".replaceAll(" |s","known$0") \$\endgroup\$
    – Arnaud
    Commented Oct 17, 2017 at 8:11
3
\$\begingroup\$

Husk, 14 bytes

OΠṠemhw¨ṅW∫ḟωμ

Try it online!

Explanation

OΠṠemhw¨ṅW∫ḟωμ
       ¨ṅW∫ḟωμ    The compressed string "knowns unknowns"
      w           Split on spaces ["knowns","unknowns"]
   e              Make a list with:
    mh             this list with the last letter dropped from each word
  Ṡ                and this same list
                  [["known","unknown"],["knowns","unknowns"]]
 Π                Cartesian product [["known","knowns"],["unknown","knowns"],["known","unknowns"],["unknown","unknowns"]]
O                 Sort the list [["known","knowns"],["known","unknowns"],["unknown","knowns"],["unknown","unknowns"]]
                  Implicitely print joining with spaces and newlines
\$\endgroup\$
3
\$\begingroup\$

6502 machine code (C64), 48 bytes

00 C0 A9 37 85 FB A9 73 4D 2B C0 8D 2B C0 A9 0D 4D 2C C0 8D 2C C0 A9 26 90 02
E9 02 A0 C0 20 1E AB 06 FB D0 E1 60 55 4E 4B 4E 4F 57 4E 53 0D 00

Online demo

Usage: sys49152


How it works

The trick here is to use a "loop counter" for 8 iterations where bits 7 to 1 of the initial value are 1 for unknown(s) and 0 for known(s) in one iteration. This counter is shifted to the left after each iteration (shifting the leftmost bit into the carry flag) and bit 0 is initially 1 so we know we're finished once the last bit was shifted out. In the first iteration, known is printed because when calling the program, the carry flag is clear.

In each iteration, the end of the string is toggled between <space> and s<newline>.

Here's the commented disassembly listing:

         00 C0            .WORD $C000    ; load address
.C:c000  A9 37            LDA #$37       ; initialize loop counter ...
.C:c002  85 FB            STA $FB        ; ... as 0011 0111, see description
.C:c004   .loop:
.C:c004  A9 73            LDA #('s'^' ') ; toggle between 's' and space
.C:c006  4D 2B C0         EOR .plural
.C:c009  8D 2B C0         STA .plural
.C:c00c  A9 0D            LDA #$0D       ; toggle between newline and 0
.C:c00e  4D 2C C0         EOR .newline
.C:c011  8D 2C C0         STA .newline
.C:c014  A9 26            LDA #<.knowns  ; start at "known" except
.C:c016  90 02            BCC .noprefix  ; when carry set from shifting $fb:
.C:c018  E9 02            SBC #$02       ; than start at "un"
.C:c01a   .noprefix:
.C:c01a  A0 C0            LDY #>.knowns  ; high-byte of string start
.C:c01c  20 1E AB         JSR $AB1E      ; output 0-terminated string
.C:c01f  06 FB            ASL $FB        ; shift loop counter
.C:c021  D0 E1            BNE .loop      ; repeat if not 0 yet
.C:c023  60               RTS            ; done
.C:c024   .unknowns:
.C:c024  55 4E           .BYTE "un"
.C:c026   .knowns:
.C:c026  4B 4E 4F 57 4E  .BYTE "known"
.C:c02b   .plural:
.C:c02b  53              .BYTE "s"
.C:c02c   .newline
.C:c02c  0D 00           .BYTE $0d, $00
\$\endgroup\$
3
\$\begingroup\$

Perl 5, 33 bytes

Disclaimer: I didn't realise that brace expansion was possible within the <...> operator (learned thanks to @Grimy's answer!) and the using the clever expansion trick from @NahuelFouilleul's amazing bash answer, I was able to build this solution. I will happily remove this at either of their request.

print<"{,un}known {,un}knowns$/">

Try it online!


Perl 5, 42 bytes

41 bytes code + 1 for -p.

s//K Ks
K unKs/;s/K/known/g;$\=s/^/un/gmr

Try it online!


Perl 5, 45 bytes

Tried to come up with an alternative, but couldn't make it shorter... Thought it was different enough to warrant adding anyway.

print"un"x/[3467]/,known,$_%2?"s
":$"for 0..7

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Haskell, 71 66 56 54 bytes

(<*>).map((++).init)<*>map(' ':)$["knowns","unknowns"]

Thanks to @Leo for -3 bytes!

Note: In the question's comments, the o.p. said that returning a list of strings is okay

Try it here.

\$\endgroup\$
3
  • \$\begingroup\$ This is great and I can't even understand it, but the part from your second fmap onwards can be shortened to map(' ':) :) \$\endgroup\$
    – Leo
    Commented Oct 17, 2017 at 3:30
  • 1
    \$\begingroup\$ @Leo Thanks! Haha, I'm not even sure I understand it anymore \$\endgroup\$
    – addison
    Commented Oct 17, 2017 at 3:55
  • \$\begingroup\$ No need to give the function a name, so you can drop the f=. \$\endgroup\$
    – nimi
    Commented Oct 17, 2017 at 6:11
3
\$\begingroup\$

Jelly, 15 bytes

“ṿ1“ŒwƘ»pż€⁾ sY

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ :( The compressed version is 29 bytes \$\endgroup\$ Commented Oct 16, 2017 at 15:47
3
\$\begingroup\$

Ruby, 53 50 bytes

$><<"a as
a unas
una as
una unas".gsub(?a,"known")
\$\endgroup\$
2
  • \$\begingroup\$ Replace \n with a literal newline. \$\endgroup\$
    – Value Ink
    Commented Jul 29, 2019 at 18:19
  • \$\begingroup\$ @ValueInk Done. \$\endgroup\$
    – anna328p
    Commented Jul 29, 2019 at 20:19
2
\$\begingroup\$

Batch, 66 bytes

@set s= in (known unknown)do @
@for %%a%s%for %%b%s%echo %%a %%bs

Alternative answer, also 66 bytes:

@for %%a in (k unk)do @for %%b in (k unk) do @echo %%anown %%bnowns
\$\endgroup\$
1
  • \$\begingroup\$ Of course, nested loops, haven't thought of that... good job! \$\endgroup\$
    – schnaader
    Commented Oct 17, 2017 at 15:49
2
\$\begingroup\$

Haxe, 71 bytes

(?x)->[for(a in x=["","un"])for(b in x)a+'known ${b}knowns'].join("\n")

Try it online!

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

Jq 1.5, 47 bytes

"K Ks
K unKs
unK Ks
unK unKs"|gsub("K";"known")

Try it online!

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

PowerShell, 46 44 bytes

' s
 uns
un s
un uns'-replace' |s','known$&'

Try it online!

(Almost) simple string replacement. Uses Neil's approach to trim two bytes. Thanks to Martin for pointing that out.

Sadly, it's shorter than the more interesting cross-product method by three five three bytes:

PowerShell, 49 47 bytes

($a='known','unknown')|%{$i=$_;$a|%{"$i $_`s"}}

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Neil's approach saves 2 bytes. \$\endgroup\$ Commented Oct 18, 2017 at 8:45
  • \$\begingroup\$ @MartinEnder Right, good call. Thanks! \$\endgroup\$ Commented Oct 18, 2017 at 12:36
2
\$\begingroup\$

T-SQL, 56 54 bytes

PRINT REPLACE('1 1s
1 un1s
un1 1s
un1 un1s',1,'known')

SQL supports line breaks inside string literals, so similar to some other languages already posted.

EDIT: Slightly longer (82 bytes), but a bit more clever:

SELECT k+s+k+p+k+s+u+p+u+s+k+p+u+s+u+p
FROM(SELECT'known'k,' 's,'unknown'u,'s
'p)t

EDIT 2: My favorite so far, using a cross-self-join from a derived table (79 bytes):

WITH t AS(SELECT'known'a UNION SELECT'unknown')
SELECT z.a+' '+t.a+'s'FROM t,t z

EDIT 3: Changed the replacement character from 'x' to 1, which lets me remove the quotes around it and save 2 bytes, since REPLACE does an implicit conversion to string.

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

Python 3, 53 bytes

for n in 2,3,5,0:u='unknowns';print(u[n&2:7],u[n%3:])

Try it online!

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

ReRegex, 38 bytes

a/known/a as\na unas\nuna as\nuna unas

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ I'm seeing this language for the first time, but a/known / z/s\n/aazaunazunaazunaunaz seems to work for 36 bytes. \$\endgroup\$ Commented Oct 17, 2017 at 3:54

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.