# The Art of Word Shaping

Given a binary matrix, and a string of letters, replace all 1's in the matrix from left, to right with the letters of the string. Once the letters have been formed into the shape of the matrix, print the matrix, replacing 0's with spaces. It's probably easier to just give an example or two.

Case: Base case...

Input One:

[0,0,1,0,0]
[0,1,0,1,0]
[1,0,0,0,1]
[0,1,0,1,0]
[0,0,1,0,0]

"PPCGPPCG"


Output One:

  P
P C
G   P
P C
G


Case: If the input string is longer than the number of ones...

Input Two:

[1,0,0]
[0,1,0]
[1,0,1]

lambda


Output Two:

l
a
m b


Case: If the input string is shorter than the number of ones...

Input Three:

[1,1,1]
[1,0,1]
[1,1,1]

PPCG


Output Three:

PPC
G P
PCG


# Available Assumptions

• You may assume the input string is never empty.
• You may assume the matrix will never be empty.
• You may not assume that the binary matrix will never be all zeros.

# Rules

• If the string is shorter than the number of ones, repeat the string; all ones must be replaced.
• If the string is longer than the number of ones, only use what is needed.
• You may use True/False in place of integers/bits for the input.
• Trailing spaces ARE REQUIRED, all zeros must be replaced with spaces.
• A single trailing newline is acceptable.
• This is code-golf, lowest byte count wins.
• Does the matrix have to be input as an array or can I use a multiline-string? Nov 14, 2016 at 15:32
• @Titus that's fine, Martin Ender already did. Nov 14, 2016 at 15:34
• The base case is not left to right. Do you mean top to bottom, then left to right? Nov 14, 2016 at 16:02
• If the matrix is, for example, a 2x2 grid of zeroes, should we output a single space or a 2x2 grid of spaces? Nov 14, 2016 at 16:28
• @pieman2201 cleared up test case #4 to be better. Nov 14, 2016 at 16:43

# Vim, 44 42 bytes

qqy$P0xjf1"_xP{@qq@q:s/0/ /g^M:s/,/^V^M/g^M{D  Saved 2 bytes thanks to @DjMcMoylex! Here, the ^M is a literal newline, and the ^V is CTRL-V Takes the input in this format: PPCG 00100,01010,10001,01010,00100  Disclaimer: If the string is longer than ~40 chars long, your computer might run out of ram. Explanation: qq @qq@q # Start recording a recursive macro. y$P0x                                         # Duplicate the string and cut out the first character
jf1"_xP{                                 # Find the first 1, and replace it with the cut character from the string.
# Now we have replaced all the 1's with their respective character, but we still have the array in the original format, and we have the string massivly duplicated at the first line, so we need to clean it up:
:s/0/ /g^M                  # Replace all 0's with a space
:s/,/^V^M/g^M     # Replace all ,'s with a newline. The ^V acts like a backslash, it escapes the newline so that the command isn't run too soon
{D   # Delete the first line


Here's a gif of me "running" the "program":

• Hahaha, love the disclaimer. Nov 14, 2016 at 17:18
• You could use { in place of gg to take a couple off. Nov 14, 2016 at 17:52
• Ok, the gif is really neat, but do you think you could include it via link only? It lags my chrome every time I try to scroll past :( Nov 15, 2016 at 14:14

## Retina, 41 33 bytes

0

+1(.)(.*)(\D+)1
$2$1$3$1
A1


Try it online!

The input string is given on the first row of the input, followed by the matrix. Since Retina has no concept of lists (or really anything except strings), there are no separators in the binary matrix except for linefeeds to separate rows.

### Explanation

0



Turns zeros into spaces.

+1(.)(.*)(\D+)1
$2$1$3$1


Repeatedly replace the first 1 with the first character of the input string while also rotating that character to the end of the input string. This takes care cases where there are more 1s than characters in the input string.

A1


Discard the first line, i.e. the input string.

• (.)(.*) - Teehee... Nov 14, 2016 at 21:06

# JavaScript ES6, 675350 49 bytes

Saved 3 bytes thanks to @ETHproductions Saved 1 more thanks to @Neil

(a,b,i)=>a.replace(/./g,c=>+c?b[++i]||b[i=0]:' ')


f=
(a,b,i)=>a.replace(/./g,c=>+c?b[++i]||b[i=0]:' ')

G=_=>h.innerHTML = f(00100
01010
10001
01010
00100,z.value)
h.innerHTML = G()
<input id=z oninput="G()" value="PPCG"></input>
<pre id=h>

Old code before I knew that string matrices are a valid input format:

(a,b)=>a.map(c=>c.map(d=>d?b[i++%b.length]:' ').join,i=0).join



f=
(a,b)=>a.map(c=>c.map(d=>d?b[i++%b.length]:' ').join,i=0).join

G=_=>h.innerHTML = f([[0,0,1,0,0],[0,1,0,1,0],[1,0,0,0,1],[0,1,0,1,0],[0,0,1,0,0]],z.value)
h.innerHTML = G()
<input id=z oninput="G()" value="PPCG"></input>
<pre id=h>

• I'd suggest c=>' '[c]||b[i++%b.length], but sadly it's a byte longer... Nov 14, 2016 at 15:51
• However, there's another way to save 3 bytes: (a,b,i)=>a.replace(/\d/g,c=>+c?b[++i]||b[i=0]:' ') Nov 14, 2016 at 15:54
• I think that will start at the second character of the string. A snippet update would be nice. Nov 14, 2016 at 16:22
• @Titus At first, i is undefined, so ++i returns NaN. Since b has no NaN property, b[++i] returns undefined, and the || operator runs its right-side argument, setting i to 0 and returning the first char in b. Nov 14, 2016 at 16:39
• Why are you testing for \d? Surely . suffices, since you only have to deal with 0s and 1s (. doesn't match newlines).
– Neil
Nov 15, 2016 at 1:44

## Perl, 40 bytes

36 bytes of code + -i -p flags.

@F=$^I=~/./g;s/1/$F[$i++%@F]/g;y;0;  (note the final space and the lack of final newline). To run it, write the input string after -i flag, and supply the matrix in the input : perl -iPPCGPPCG -pe '@F=$^I=~/./g;s/1/$F[$i++%@F]/g;y;0; ' <<< "00100
01010
10001
01010
00100"


If your Perl is a bit old, you might need to add a final semicolon (after the space).

# Python 2, 114 71 bytes

Turns out I was re-inventing the wheel, a simple double replace on a multiline string works quite well. The string has the additional benefit of being able to count zeros directly rather than having to do the really ugly s*len(L)*len(L[0]) for a nested list

lambda S,s:S.replace("0"," ").replace("1","{}").format(*s*S.count('0'))


Old solution:

lambda s,L:"\n".join(["".join(map(lambda n:chr(n+32),l)).replace("!","{}")for l in L]).format(*s*len(L)*len(L[0]))


First we convert everything + 32 with chr (all zeros become spaces), then we replace all of the ! with {} to allow using the format function.

If NULL can be counted as a space If I decide to cheat and use NULL instead of space, I can skip the addition of 32 to save 12 bytes. (print displays '\x00' as a space)

lambda s,L:"\n".join(["".join(map(chr,l)).replace('\x01','{}')for l in L]).format(*s*len(L)*len(L[0]))

• Wouldn't it be shorter to use the NULLs, and replace them with space at the end? Nov 15, 2016 at 12:53
• @nedla2004, How do you suggest I do that? Just adding a .replace('\x00',' ') on the end adds 20 bytes Nov 15, 2016 at 14:04
• But then I think you could get rid of this: map(lambda n:chr(n+32),l) Nov 15, 2016 at 14:10
• The second solution works with NULLs the whole time, which saves me 12 bytes, swapping to spaces at the end will cost me more than that Nov 15, 2016 at 14:11
• I thought you could remove more than you actually can. Nov 16, 2016 at 1:32

# MATL, 11 bytes

yz:)1Gg!(c!


Inputs are a numeric matrix (with ; as row separator) and a string.

Try it online! Or verify test cases: 1, 2, 3.

y       % Take the two inputs implicitly. Duplicate the first
% STACK: [1,0,0; 0,1,0; 1,0,1], 'lambda', [1,0,0; 0,1,0; 1,0,1]
z       % Number of nonzeros
% STACK: [1,0,0; 0,1,0; 1,0,1], 'lambda', 4
:       % Range
% STACK: [1,0,0; 0,1,0; 1,0,1], 'lambda', [1 2 3 4]
)       % Reference indexing (select values)
% STACK: [1,0,0; 0,1,0; 1,0,1], 'lamb'
1Gg     % Push first input as a logical matrix; will be used as index
% STACK: [1,0,0; 0,1,0; 1,0,1], 'lamb', [1,0,0; 0,1,0; 1,0,1]
!       % Transpose. This is necessary because MATL uses column-major order
% (down, then accross)
(       % Assignment indexing (fill with values). Since the original matrix
% is numeric, the new values are introduced as their ASCII codes
% STACK: [108, 0, 109; 0, 97, 0; 1, 0, 98]
c       % Convert to char
% STACK: ['l m'; ' a '; '  b']
!       % Transpose back. Implicitly display
% STACK: ['l  '; ' a '; 'm b']

• MATL basically redefines how I've always seen collections... Nov 14, 2016 at 16:45
• @carusocomputing Like in Matlab, the main data type is "rectangular" arrays: matrices or their n-dimensional analogues. They can contain numbers, chars or Boolean values. There are also cell arrays, that can contain arbitrary things, like Python's lists Nov 14, 2016 at 19:13
• Best answer selected after 2 weeks open. Nov 30, 2016 at 22:41

# APL, 18 bytes

{(⍴⍺)⍴X\⍵⍴⍨+/X←,⍺}


This is a function that takes a boolean matrix as its left argument and a string as its right argument.

      (↑(1 0 0)(0 1 0)(1 0 1)) {(⍴⍺)⍴X\⍵⍴⍨+/X←,⍺}'lambda'
l
a
m b


Explanation:

APL has a built-in that does something like this, \ (expand). However, it only works on vectors, and it requires each character to be actually used.

• X←,⍺: flatten the matrix and store the result in X.
• ⍵⍴⍨+/X: reshape the character vector so that it has the required amount of elements (this also takes care of lengthening the string by repeating characters if necessary).
• X\: take one of the characters for each 1 and a space for each 0 in X.
• (⍴⍺)⍴: reshape the result so that it has the shape of the original matrix.

# PHP, 110919788828180 75 bytes

saved 6 bytes thanks to @user59178

while(""<$c=$argv[1][$i++])echo$c<1?$c?:" ":($s=$argv[2])[$k++%strlen($s)];  Run with -r. Expects matrix as multiline string in first argument, string in second argument. • An 80 byte version based on your 82 bytes version: foreach(str_split($argv[1])as$c)echo$c<1?$c?:" ":($s=$argv[2])[$k++%strlen($s)]; I swapped the order of the two ternaries and thus dropped the brackets from the second by using <1 rather than >0 Nov 14, 2016 at 16:27 • you could save 4 bytes by using for(;""!=$c=$argv[1][$i++];) instead of the foreach(...) Nov 14, 2016 at 17:30

## PowerShell v2+, 70 bytes

param($a,$b)$b|%{-join($_|%{if($_){$a[$n++];$n%=$a.length}else{' '}})}  Takes input word as $a and the matrix as an array-of-arrays as $b (see examples below). Loops through $b, then loops through the elements of each row $_|%{...}. Inner loop is an if/else condition, where we either output $a[\$n++] and take mod-equal to the length of the string, or output a space ' '. Those are -joined together back into a string. Each of the strings is left on the pipeline, and implicit output with newlines between happens via Write-Output at program completion.

PS C:\Tools\Scripts\golfing> .\the-art-of-word-shaping.ps1 'PPCGPPCG' @(@(0,0,1,0,0),@(0,1,0,1,0),@(1,0,0,0,1),@(0,1,0,1,0),@(0,0,1,0,0))
P
P C
G   P
P C
G

PS C:\Tools\Scripts\golfing> .\the-art-of-word-shaping.ps1 'lambda' @(@(1,0,0),@(0,1,0),@(1,0,1))
l
a
m b

PS C:\Tools\Scripts\golfing> .\the-art-of-word-shaping.ps1 'PPCG' @(@(1,1,1),@(1,0,1),@(1,1,1))
PPC
G P
PCG


## Python 3, 104 (or 83) Bytes

import itertools as i
def f(s,L):s=i.cycle(s);return'\n'.join(' '.join(next(s)*e for e in l)for l in L)


There is shorter option (83 Bytes), but it will fail if string is more than 999 times shorter than needed:

def f(s,L):s=list(s)*999;return'\n'.join(' '.join(s.pop(0)*e for e in l)for l in L)

• Second solution doesn't work for me, because you can't call next on a list. If you do s=iter(list(s)*999) it does (89 bytes) Nov 15, 2016 at 11:38
• @L3viathan sorry, I meant it to be s.pop(0). Seems that I copied wrong version, fixed that. Nov 15, 2016 at 12:36
• s[i++%s.length()] is a good methodology, though I don't know python. Nov 15, 2016 at 20:01
• It would be cool, but there is no such thing as i++ in Python Nov 16, 2016 at 12:19

# Groovy, 63

{a,b->i=0;a.replaceAll("1",{b[i++%b.size()]}).replace("0"," ")}


# Pyth, 12 bytes

jms?R@z~hZ\


Try it online: Demonstration

### Explanation:

jms?R@z~hZ\ dQ   implicit d and Q at the end
I use the variable Z, which is initialized with 0 by default
m           Q   map each line d of the Q (input matrix) to:
?R       d       map each number d of the line either to
@z~hZ             input[Z++] (increase Z, but lookup in input string with old value)
\            or space
s                 join chars to a string
j                print each string on a separate line


## ES6, 78 bytes

  (a,b,x=0)=>(b.map(r=>r.map(i=>i?a[x++%a.length]:' ')+'\n')+'').replace(/,/g,'')


I tried

• Welcome to PPCG! Nov 15, 2016 at 14:04

# Common Lisp, 152 bytes

(defun m(g w)(let((a 0))(loop for r in g do(loop for e in r do(format t"~[ ~;~c~]"e(char w a))(if(= e 1)(setf a(mod(1+ a)(length w)))))(format t"~%"))))


Usage:

* (m (list (list 1 0 1)
(list 0 1 0)
(list 1 0 1)) "ppcg")
p p
c
g p


This function loops through each element of each row of the grid. The format control string either prints a space if the element is a 0 or consumes the character argument if the element is 1. A newline gets printed after every row of the grid. If the string is too short, it repeats from the beginning; if it's too long, only the appropriate part gets outputted.

## Pip, 18 bytes

17 bytes of code, +1 for -l flag.

Yb{a?y@++vs}MMa^s


Takes the array as the first command-line argument like this: 100 010 101 (needs to be quoted in shells) and the string as the second command-line argument. Try it online!

### Explanation

                   a and b are cmdline args, s is space, v is -1
Yb                 Yank b into global variable y
a^s  Split a on space into list of rows
{        }MM     Map this function to the items of the items of a (i.e. each character):
a               Function argument
?              Ternary operator (truthy if 1, falsey if 0)
++v         If truthy, increment v...
y@            ... and use it to index into y (cyclically)
I.e.: each time we hit a 1, replace it with the next character of y
s        If falsey, space
The result is a list of lists of characters; -l concats sublists and
newline-separates the main list


# Java, 237 233 Bytes

Edit: saved 4 Bytes thanks to Mukul Kumar

Golfed:

String T(int[][]m,String b){int l=m.length,a=0;String o="";for(int i=0;i<l;i++){for(int j=0;j<l;j++){if(m[i][j]==1&&a<b.length()){o+=Character.toString(b.toCharArray()[a]);a++;if(a== b.length()-1)a=0;}else o+=" ";}o+="\n";}return o;}


Ungolfed:

public String T(int[][] m, String b) {
int l = m.length,a=0;
String o = "";
for(int i = 0; i < l; i++)
{
for(int j = 0; j < l; j++)
{
if(m[i][j] == 1 && a < b.length())
{
o += Character.toString(b.toCharArray()[a]);
a++;

if(a == b.length() - 1)
a = 0;
}
else
o += " ";
}
o += "\n";
}
return o;
}


Testing:

  int[][] matrix = new int[][]
{{ 0, 0, 1, 0, 0 }, { 0, 1, 0, 1, 0 },
{ 1, 0, 0, 0, 1 },{ 0, 1, 0, 1, 0 },
{ 0, 0, 1, 0, 0 },};
TheArtOfWordShaping taows = new TheArtOfWordShaping();
System.out.println(taows.T(matrix, "PPCGPPCG"));

matrix = new int[][] {{1,0,0}, {0,1,0}, {1,0, 1}};
taows = new TheArtOfWordShaping();
System.out.println(taows.T(matrix, "lamda"));

matrix = new int[][] {{1,1,1},{1,0,1},{1,1, 1}};
taows = new TheArtOfWordShaping();
System.out.println(taows.T(matrix, "PPCG"));

P
P C
G   P
P C
P

l
a
m d

PPC
P P
CPP

• You can declare all int in one line..... Nov 15, 2016 at 5:17

## Pyke, 12 bytes

.FdRIKQoQl%@


Try it here!

Outputs a matrix of characters

Or 9 bytes, noncompetitive.

.FdRIKQo@


Try it here!

• Add wrapping on indexables where the index asked for is bigger than the length of the indexable. ​ .F - deep_for(input) I - if ^: Qo@ - Q[o++] dR - else " "

Even more noncompetitive, 8 bytes

.FIQo@(P


Try it here!

• print_grid now aligns empty strings properly
• deep_for now does type-guessing on falsies of a different type to the truthies

.F    (  -  deep_for(input)
I       -   if ^:
Qo@    -    input[o++]
P - pretty_print(^)


# Java,122 bytes

String g(int[][]a,char[]b){String r="";int e=0;for(int[]c:a){for(int d:c){r+=d==0?' ':b[e++%b.length];}r+='\n';}return r;}


# Mathematica, 76 bytes

""<>(s=#2;f:=(s=RotateLeft[s];Last[s]);Map[If[#1,f," "]&,#,{2}]~Riffle~"\n")&


Unnamed function of two arguments, the first of which (#) is an array of Trues and Falses, and the second of which (s) is a list of characters. The helper function

f:=(s=RotateLeft[s];Last[s])


is defined, which puts the moves the first character of s to the end and then returns that just-moved character. Calling f several times will cyclically return the characters of s in order.

The core function is

Map[If[#1,f," "]&,#,{2}]


which calls f on every True value in the input array and returns a space on every false input. (The {2} tells Map to work on elements of the array's component lists, rather than those lists themselves.)

Those 60 bytes return an array of characters-of-s and spaces. The wrapper

    ""<>(...~Riffle~"\n")&


puts newlines between each of that array's lists and then concatenates everything.

# C++, 61 bytes

for(auto&i:m){for(int&j:i)cout<<(j?s[k++%l]:' ');cout<<'\n';}