# Make a haystack (with a needle)

(Essentially the inverse of Find the needle in the haystack)

Given two tuples, (w, h) and (x, y), generate a haystack composed of a single random printable ASCII character of w width and h height with a needle made of a different random printable ASCII character at (x, y) when measured from the upper-left.

For example, when given (5,4) for the width and height, and (3,1) (zero-indexed) for the location of the needle, a possible haystack could be the following:

#####
###N#
#####
#####


Another possibility could be

*****
**** ***** *****  among hundreds of others. ### Rules and Clarifications • Input and output can be given by any convenient method. This means you can take input as a list of list of integers, as a single string, as two integers via command-line and a tuple via function argument, etc. • You can print the result to STDOUT or return it as a function result. • Either a full program or a function are acceptable. • You can choose whether the (x, y) tuple is zero-indexed or one-indexed, but please specify in your solution which you're using. • You do not get to pick which characters to use. That's part of the challenge - randomly selecting the characters. • Every possible output for a given input must have a non-zero chance of appearing, but the randomness doesn't need to be uniform. • The haystack is guaranteed to be at least 2x2 in size, so it's unambiguous which is the needle and which is the hay. • There is only ever one needle, and it's only ever one character in size, and it's guaranteed to be within the boundaries of the haystack. • Standard loopholes are forbidden. • This is so all usual golfing rules apply, and the shortest code (in bytes) wins. • Can we return a flat list of characters? – TFeld Oct 16 '19 at 15:02 • Obligatory xkcd about the choice of the characters. Applies to a few early answers... :p – Arnauld Oct 16 '19 at 15:34 • @Arnauld I don't know what was the magic here, but I completely read the challenge as I can use any ASCII printable characters "that I like", instead of "random", and it is funny another person also did same exact thing! I didn't mean to implement the random in such a beautiful way :P – Night2 Oct 16 '19 at 16:17 • @UnrelatedString Yes and yes? Those are standard I/O rules. – AdmBorkBork Oct 17 '19 at 12:23 • @TaylorScott Yes, that's covered in the opening paragraph. The two characters need to be different. – AdmBorkBork Nov 18 '19 at 13:34 ## 33 Answers # JavaScript (Node.js), 122 120 106 103 bytes Recursively builds the output character by character. The coordinates are 0-indexed. (w,h,x,y)=>(s=new Date%9023,g=X=>Y<h?Buffer([X-w?(x-X|y-Y?s+1:s%96)%95+32:13])+g(X<w?X+1:!++Y):'')(Y=0)  Try it online! ## How? ### Problem To generate the haystack and the needle, we could either: • generate a random haystack and process some loop to generate a random needle until it's different from the haystack • shuffle the whole range of printable characters and pick the first 2 of them Unfortunately, both approaches are rather lengthy in JS. ### Solution We use instead a method that guarantees to generate 2 distinct characters with a single random number and without any loop. We pick a random seed $$\s\$$ in $$\[0..9022]\$$ and define the haystack $$\h\$$ and needle $$\n\$$ as: \begin{align}&h=(s+1)\bmod 95\\ &n=(s\bmod 96)\bmod 95\end{align} (we then need to add $$\32\$$ to turn them into printable ASCII codes) Basically, $$\h\$$ follows the pattern: $$1,2,3,...,94,0,1,2,3,...$$ while $$\n\$$ follows the pattern: $$0,1,2,3,...,94,\color{red}0,0,1,2,3,...$$ The sequences are progressively shifted relative to each other because of the extra $$\0\$$ in the needle pattern. This code shows that it does eventually lead to all possible pairs $$\(h,n)\$$ with $$\h\neq n\$$ (there are $$\95\times 94=8930\$$ of them). And because we need only one random number, we can afford to use the current timestamp in milliseconds as our entropy source with new Date%9023 instead of the longer Math.random()*9023. ## Commented (w, h, x, y) => ( // w = width, h = height, (x, y) = coordinates s = new Date % 9023, // s = random seed in [0..9022] g = X => // g = recursive function taking X Y < h ? // if we've not reached the end of the grid: Buffer([ // append the next character: X - w ? // if we haven't reached the end of the line: ( x - X | // if this is not the position of the needle: y - Y ? // s + 1 // append the haystack character : // else: s % 96 // append the needle character ) % 95 + 32 // : // else: 13 // append a linefeed ]) + // g(X < w ? X + 1 // append the result of a recursive call : !++Y) // with either (X+1, Y) or (0, Y+1) : // else: '' // stop recursion )(Y = 0) // initial call to g with X = Y = 0  • Never seen new Date be used to generate a random seed before. Cool. – Daniel Vestøl Oct 17 '19 at 12:00 • @DanielVestøl, it's a common tactic in challenges where "random" is un(der)specified. – Shaggy Oct 17 '19 at 23:30 # Jelly, 14 13 bytes p/⁼€ịØṖẊ¤s⁸Ḣ¤  Try it online! -1 byte thanks to Unrelated String Returns a list of lines. The last line in the Footer section displays it as a square. Takes input as [w, h] and [y, x], where x and y are 0-indexed. ## How it works p/⁼€ịØṖẊ¤s⁸Ḣ¤ - Main link. Takes [w, h] on the left and [y, x] on the right p/ - Reduce Cartesian product over the arguments. This yields a list of co-ordinates from (1, 1) to (h, w) € - Over each list: ⁼ - Is it equal to [x, y]? - This yields a list where every element except 1 is 0 ¤ - Create a nilad: ØṖ - Printable ASCII characters Ẋ - Shuffled ị - Index into the shuffled characters, replacing 1 with the first char in the shuffled list and 0 with the last. Therefore, the two characters will be distinct ¤ - Create a nilad: ⁸ - Yield [w, h] Ḣ - Extract w s - Split the list of characters into rows of length w - Implicitly output  • -1 byte if you take [y, x] instead of [x, y] so you can drop the U – Unrelated String Oct 17 '19 at 12:29 • @UnrelatedString Huh, weird. That didn't work for me when I first posted it, but is now. Thanks! – caird coinheringaahing Oct 17 '19 at 12:34 # Excel VBA, 12811810694 96 bytes -12 bytes inspired by agtoever -12 bytes thanks to Taylor Scott, VBA extraordinaire +2 bytes and -1 bug thanks to Taylor's unnecessary, intimidating, and much appreciated work Sub n(w,h,x,y) a=94*Rnd [A1].Resize(h,w)=Chr(a+32) Cells(y,x)=Chr(32+(a+93*Rnd+1)Mod 95) End Sub  Input and output are one-indexed. Output is to the top left cell range of the active sheet. a=94*Rnd+32: (126-32)*Rnd+32 gives a number between 32 and 126, inclusive. Range(~)=Chr(a): Fills all the cells with the ASCII character. Cells(y,x)=Chr(~): Fills just that one cell with the other ASCII character. (a+62*Rnd)Mod 95+32: {(a+[94-32]*Rnd) Mod (126-32+1)}+32 gives a random number between 32 and 126 inclusive that is not the same as a. (I can't prove that mathematically but 100 million tests showed no collisions.) Example output: • Shorter: b=Chr(Asc(a)+1+95*Rnd Mod 127) instead of the do-while loop. – agtoever Oct 20 '19 at 6:53 • Oh. And then you can just insert that statement in Cells(y,x)=... instead of assigning it to b. – agtoever Oct 20 '19 at 6:55 • @agtoever I tried that when I was trying to get the previous suggestion to work. As written, b ends up in the range 0-126 instead of 32-126 although it's always unique from a. I massaged it a bit to get the most recent edit, which had 0% failure rate over 100 million runs. – Engineer Toast Oct 22 '19 at 14:17 • You can get down to 94 bytes if you use [A1].Resize(h,w)=Chr(a) – Taylor Scott Nov 14 '19 at 22:36 • The 62 in the needle declaration didn't quite sit well with me, so I went and checked the math - it looks like as written it does avoid all possible collisions of a and b, but, it also fails to give 31 expected b values for every a value. I did work out a solution to this should only cost you two bytes - a=94*Rnd, Chr(a+32) and Chr(32+(a+93*Rnd+1)Mod 95) should give you everything you need. Uh, I've also been working on my own commenting and formatting habits, so here is a needlessly well commented proof of the above. Cheers! – Taylor Scott Nov 16 '19 at 23:47 # PowerShell v6, 102 96 bytes param(x,$y,$a,$b)$j,$k=' '..'~'|random -C 2 -join((,$j*$x+++' ')*$y|%{"$_$k"[$i++-eq$b*$x+$a]})


Try it online!

This answer, thanks to mazzy, uses the character range feature added in v6 to save several bytes over the more flexible answer below.

# PowerShell, 119..105 102 bytes

-16 bytes thanks to mazzy

param($x,$y,$a,$b)$j,$k=32..126|random -C 2
-join((,$j*$x+++'
){$F[3]}.{$F[2]}\K.;$b  Try it online! # Julia 1.0, 71 bytes f(w,h,x,y)=(z=unique(rand(' ':'~',9));g=fill(z[1],(h,w));g[y,x]=z[2];g)  x,y are one indexed. Returns a 2d array of characters, I spent the extra bytes to make sure the default printing has the right orientation (' for transpose no longer works because they stick to a strict mathematical meaning). Getting two distinct randoms is surprisingly verbose, this has about a 1e-18 chance of failing to do so, one more byte could make it 1e-196. Try it online! # J, 21 bytes u:@(32+2?95){~#.=i.@[  Try it online! Inspired by dzaima's APL answer. Thanks to Galen and Adam for the randomize fix. • Fix by Adam – Galen Ivanov Oct 16 '19 at 16:15 • You need two tuples as input – Galen Ivanov Oct 16 '19 at 16:18 • Yeah I just noticed that, will fix. Thanks for the other fix btw. – Jonah Oct 16 '19 at 16:19 # Octave with Statistics Package, 45 bytes @(x)randsample(' ':'~',2)(sparse(x{:},0:1)+1)  The input is a cell array of 2 numeric vectors of length 2: {[h y] [w x]}, with x,y 1-based. Try it online! # Ruby, 62 bytes ->w,h,x,y{a,b=[*?\s..?~].sample 2;r=[a*w]*h*$/;r[y*-~w+x]=b;r}


Try it online!

# Pyth, 565048 41 bytes

JEKE=TE=Yrd\~=Zh.SYVJVQ ?qHK?qNTpeYpZpZ)d


I'm somewhat struggling to golf Pyth, but posting this to force myself to learn.

Edit 1: Golfed it down a bit, and made it an actual solution -6 bytes

Edit 2: Looked at it after posting it and realized a few bytes save by ignoring space. -2 bytes

Edit 3: Today I learned about character ranges, which shortens things significantly. -7 bytes

# Excel + CSV, 104 bytes

,,,,=94*RAND()+32,=REPLACE(REPT(REPT(CHAR(E1),A1)&"
",B1),D1*A1+D1+C1+1,1,CHAR(MOD(E1+62*RAND(),95)+32))


Save as CSV, add input as A1 - D1. Output will be in F1.

Using @Engineer Toast's solutoin for generating 2 unique characters.

Needle position is 0-indexed, which is curious, as Excel itself if 1-indexed. Changing to 1-indexed input adds 3 bytes ((D2-1)*(A2+1)+C2 instead of D1*A1+D1+C1+1).

• @Arnauld, it does not. Thanks for poingin out. Have updated. – Wernisch Oct 29 '19 at 10:34
• Just wanted to let you know that the indicated solution for the needle character is not quite correct. You should switch to CHAR(MOD(E1+93*RAND()+1,95)+32) to insure that your solution covers all possible combinations of needle and haystack – Taylor Scott Nov 22 '19 at 20:21

# SOGL, 18 bytes

 ~Δψ] ~Δψ⁴⁴=}A*∙až


Try it here! 1-indexed.

D,g,?!,
L,c95Rdb[€BXd¦=BFV#@G+b[95€Ω%31€+€CA€RbU‽g$€=$€Ω:A$pbUp$T


Try it online!

Takes input as [y x] and [w h]. x and y are 1-indexed. Outputs a list of lines.

Added 17 bytes to make sure the needle is distinct.

## How it works

We start by generating two ranges from $$\1\$$ to $$\95\$$ inclusive, before choosing a random value from each. If the two values are equal, we add one to the one of them. We then add $$\31\$$ to each, yielding two characters ord points in the ASCII range. Finally, we convert them to characters.

Next, we generate a list of all co-ordinates in the grid, and compare them with [y x]. If the co-ordinates match, we yield $$\1\$$, otherwise $$\0\$$. Next, we index each of these $$\1\$$s and $$\0\$$s into the two characters, creating a grid of $$\0\$$ characters with 1 $$\1\$$ character in it at [y x]. Finally, we retrieve the width and split the grid into that many rows.

# PHP, 113 109 bytes

for([,$w,$h,$x,$y]=$argv,$a=range(' ','~'),shuffle($a);$i++<$h;print" ")for(;$$i++i-$x];


Try it online!

Pass inputs as command arguments ($argv) in order of w, h, x and y. The x and y are one-indexed. for( [,$w,$h,$x,$y]=$argv, // put inputs from $argv array into 4 short named variables$a=range(' ','~'),    // create $a array containing printable ASCII characters shuffle($a);          // shuffle the array
$i++<$h;              // loop $h times (rows) print"\n" // print a newline after every row ) for(;$$i++i-$x          //   or when col and x don't match (will be false only for needle)
];


# C# (Visual C# Interactive Compiler), 145 bytes

(a,b,c,d)=>{int l=0;for(var j=Enumerable.Range(32,95).OrderBy(k=>Guid.NewGuid()).ToList();l<a*b;)Write((char)j[l==c*a+d?1:0]+(++l%a<1?"\n":""));}


Try it online!

# Icon, 119 bytes

procedure f(w,h,x,y)
until m:=char(32+?95)&n:=char(32+?95)&m~==n
t:=[];1to h&put(t,repl(m,w))&\z
t[y,x]:=n
return t
end


Try it online!

xand yare 1-indexed

# Python 3, 137 bytes

lambda w,h,x,y,c=chr:"\n".join([c(a)*w,c(a)*x+c(n)+c(a)*(w-x-1)][r==y]for r in range(h));a,n=__import__("random").sample(range(32,127),2)


Try it online!

Uses zero-based indexing for the needle position.

• from random import* is shorter than __import__("random"). 136 bytes. – Value Ink Oct 17 '19 at 0:54

# Perl 6, 57 bytes

{(' '..'~').pick(2)[0 xx$^a*$^b-1,1;*].pick(*).rotor($a)}  Try it online! # Charcoal, 17 bytes ＵＯＮＮ‽γＪＮＮ‽Φγ¬⁼ιＫＫ  Try it online! Link is to verbose version of code. Explanation: ＵＯＮＮ‽γ  Draw a rectangle of the given width and height using a random printable ASCII character. ＪＮＮ  Jump to the 0-indexed position of the needle. ‽Φγ¬⁼ιＫＫ  Print a random printable ASCII character, but filtering out the character under the cursor. # Red, 156 bytes func[w h x y][c: :collect p: take/part random c[repeat i 95[keep to sp 32 + i]]2 c[repeat i h[keep/only c[repeat j w[keep pick p i * w + j =(y * w + x)]]]]]  Try it online! x and y are 1-indexed. Returns a list of strings. ## Readable: f: func [w h x y] [ c: take/part random collect [ repeat i 95 [ keep to sp 32 + i ] ] 2 collect[ repeat i h [ keep/only collect [ repeat j w [ keep pick c i * w + j = (y * w + x) ] ] ] ] ]  # Python 2, 144132 131 bytes from random import* i,j,k,l=input() n,h=sample(range(32,127),2) for x in range(j):a=[chr(n)]*i;a[k]=chr((n,h)[x==l]);printa[2::5]  Try it online! Corrected the problem with the guaranteed uniqueness of the characters and saved 12 bytes along the way. • I liked the idea of this solution well enough that I shaved off 3 more bytes for you: tio.run/… – quintopia Oct 30 '19 at 9:16 • Nice and also different enough for you to post as your own if you wish :) – ElPedro Oct 30 '19 at 12:28 • Eh, it's not that different. It is a direct modification of yours edited directly on TIO. Posting it separately would have been actual effort. – quintopia Oct 30 '19 at 19:02 # Forth (gforth), 140 bytes include random.fs : x 95 random 32 + ; : f x -rot 0 do cr dup 0 do 2over i j d= >r over r> if begin x 2dup - until nip then emit loop loop ;  Try it online! 0-indexed ### Code Explanation include random.fs \ import the random library \ Generate a random number in range 32 to 126 inclusive : x \ start a new word definition 95 random \ generate a random number between 0 and 94 32 + \ add 32 ; \ end word definition : f \ start a new word definition x -rot \ generate a random number for the haystack, then move it 0 do \ loop from 0 to h-1 (inclusive) cr \ output a newline dup 0 do \ loop from 0 to w-1 (inclusive) 2over i j d= \ check if this is the needle square >r over r> \ hide result, grab a copy of the haystack char, then grab result back if \ if it is a needle begin \ begin indefinite loop x 2dup - \ generate a new random number and compare to haystack char until \ only end loop when values differ nip \ drop haystack char then \ end if block emit \ output ascii char for value on top of stack loop \ end row loop loop \ end column loop ; \ end word definition  # C (clang), 87 bytes f(w,h,x,y){x+=y*w;h*=++w;for(y=time(0)%9023;h--;)putchar(h%w?(x--?y+1:y%96)%95+32:10);}  Try it online! Stealing from @Arnauld answer # K (oK), 27 23 bytes -4 bytes thanks to ngn! {c$(32+-2?95)x#&/y=!x}


Try it online!

0-indexed x and y

Similar to Dzaima's APL and Jonah's J solutions.

• (x/y)=x#!*/x -> x#&/y=!x – ngn Oct 19 '19 at 17:17
• @ngn That's much better than my naive solution. Thanks! – Galen Ivanov Oct 19 '19 at 18:34
• @ngn Clever use of the odometer for 2d matching! – Galen Ivanov Oct 19 '19 at 18:47

# 05AB1E, 15 bytes

žQΩIP×žQΩIPǝ¹нô


Coordinates are 1-indexed. Outputs as a list of lines.

Try it online (» in the footer joins the list of strings by newlines to pretty-print, feel free to remove it to see the actual output).

Explanation:

žQ              # Push all printable ASCII characters
Ω             # Pop and push a random character
IP           # Push the first input (rectangle-size), and take its product
×          # Repeat the random character that many times as string
žQΩ       # Push a random character again
IP     # Push the second input (1-based coordinate), and take its product as well
ǝ    # Insert the random character at this (0-based) index into the string
¹н  # Push the first input again, and only leave its first value (width)
ô # Split the string into parts of that size
# (after which the resulting list of strings it output implicitly as result)
`