20
\$\begingroup\$

You are given a single printable ASCII string containing no newlines, and a multiline "mold", containing spaces (), and hashes (#).

You must go character by character in the string, and replace hashes using the characters from the string in left-right, top-bottom order. If the string is too short to fill the mold, you stop outputting, if the string is too long you truncate the string to exactly fill the mold.


Example string/mold (string too long, truncated):

Loremipsumdolorsitamet,consecteturadipiscingelit.Namsuscipitmagnanoneratgravidacondimentum.Vestibulumnecnisllorem.Fuscemolestieviverranibh,eueleifendnislplaceratnon.Namblanditturpislacus,vitaemolestielacusimperdietquis.Nullapulvinar,exquissollicitudinfacilisis,eratnullavolutpatlectus,etluctusenimvelitegetex.Inhachabitasseplateadictumst.Donecinterdumnullalacinia,sodalesloremin,eleifendturpis.Pellentesqueanisimi.Aeneannonlobortisdiam,quisaliquetquam.Aeneanaugueipsum,imperdietsedaliquetnon,volutpategetsapien.Nullampharetranullaquispretiumornare.Aliquamfermentumvestibulummassavitaevehicula.
###########################################################
##### ##############   ###### ###### ######################
#####  ##   ######   #  ##### ###### ########        ######
###### #  #  ####  #### ##### ###### #######  ######  #####
######   ###  ###       ##### ###### ####### #######  #####
######  ##### ### ########### ###### #######   ###   ######
###### ###### ###  ########## ######      #####   #########
##################       ####    ##########################
###########################################################

Example output:

Loremipsumdolorsitamet,consecteturadipiscingelit.Namsuscipi
tmagn anoneratgravid   acondi mentum .Vestibulumnecnisllore
m.Fus  ce   molest   i  evive rranib h,euelei        fendni
slplac e  r  atno  n.Na mblan dittur pislacu  s,vita  emole
stiela   cus  imp       erdie tquis. Nullapu lvinar,  exqui
ssolli  citud inf acilisis,er atnull avolutp   atl   ectus,
etluct usenim vel  itegetex.I nhacha      bitas   seplatead
ictumst.Donecinter       dumn    ullalacinia,sodalesloremin
,eleifendturpis.Pellentesqueanisimi.Aeneannonlobortisdiam,q

Example string/mold (string too short, output stopped):

This probably won't look good.
### ### ### ###
# # # # #   #
### ### #   # #
#   #   #   # #
#   #   ### ###

Corresponding output:

Thi s p rob abl
y   w o n   '
t l ook     g o
o   d   .   

Shortest code in bytes wins.

Credit for the idea to this website.

\$\endgroup\$
8
  • 2
    \$\begingroup\$ Can the input line contain hashes? (If so, that could use a test case.) \$\endgroup\$ Commented Feb 8, 2016 at 10:17
  • \$\begingroup\$ Can the input line contain spaces? \$\endgroup\$
    – manatwork
    Commented Feb 8, 2016 at 10:42
  • 2
    \$\begingroup\$ @MartinBüttner Yes, the input case can contain hashes. \$\endgroup\$
    – orlp
    Commented Feb 8, 2016 at 12:45
  • 1
    \$\begingroup\$ Can the output have trailing whitespace if the string is too short? \$\endgroup\$ Commented Feb 8, 2016 at 19:10
  • 1
    \$\begingroup\$ @Pietu1998 No, the specification is exact. Only the standard single trailing newline is allowed. \$\endgroup\$
    – orlp
    Commented Feb 8, 2016 at 19:18

18 Answers 18

9
\$\begingroup\$

LabVIEW, 37 LabVIEW Primitives

splits the string into text and mold then transforms them into an array. Checks the mold if theres a # and puts a char from text else it does nothing. If either the text or the mold are empty exit the loop

\$\endgroup\$
2
  • \$\begingroup\$ The fact that you did this with LabView blows \$\endgroup\$ Commented Feb 8, 2016 at 19:39
  • \$\begingroup\$ AND its fun to look at! \$\endgroup\$ Commented Feb 8, 2016 at 21:41
7
\$\begingroup\$

Haskell, 48 bytes

called like "(replace with string)#(hashmark string)":

[]#_=[]
(r:t)#('#':s)=r:t#s
r#(c:s)=c:r#s
_#_=[]

Less golfed:

combine replacements slots | null replacements = []
                           | null slots        = []
                           | head slots == '#' = head replacements : combine (tail replacements) (tail slots)
                           | otherwise         = head slots        : combine       replacements  (tail slots)
\$\endgroup\$
2
  • \$\begingroup\$ Cool, but isn't this invalid unless you add I/O? E.g import Control.Applicative;main=liftA2(#)getLine getContents>>=putStrLn \$\endgroup\$
    – Cubic
    Commented Feb 9, 2016 at 14:53
  • \$\begingroup\$ @Cubic The problem statement does not require IO (or even a full program) and other solutions, including one in Python 3, do not include IO. \$\endgroup\$ Commented Feb 10, 2016 at 0:20
5
\$\begingroup\$

CJam, 16 14 bytes

Thanks to Sp3000 for saving 2 bytes.

lq{s'#-\+(\}/;

Terminates with an error if the string is too short, but the error is printed to STDERR.

Try it online!

Alternatively (same byte count):

lq{SN+&\+(\}/;

Explanation

l       e# Read the input line.
q       e# Read the grid.
{       e# For each character in the grid...
  s     e#   Convert to string.
  '#-   e#   Remove "#" from it.
  \+    e#   Prepend it to the input line (this is a no-op for "#"s in the grid).
  (     e#   Pull off the first character from the input line. This will terminate the
        e#   program with an error once the input line is empty.
  \     e#   Swap the character with the input line.
}/
;       e# Discard the remainder of the input line if there is any.
\$\endgroup\$
5
\$\begingroup\$

Retina, 42 40 bytes

Byte count assumes ISO 8859-1 encoding.

T`#`×`¶.+
+`^(.)([^×]+)×
$2$1
^.*¶|×\D*

The trailing linefeed is significant.

Try it online!

Explanation

T`#`×`¶.+

We first replace # which are part of the grid with the non-ASCII (but extended ASCII) character × so we don't confuse them with any # that might appear on the first line.

+`^(.)([^×]+)×
$2$1

Now we fill as many × as possible from the first line by repeatedly replacing the first × we can find with the first character on the first line (which is removed in the process).

^.*¶|×\D*

Finally, we get rid of anything that's left on the first line as well as anything from the first × to truncate the input in both directions.

\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6), 57 56 55 bytes

(s,m)=>m.replace(x=/[^]/g,c=>c-1?x&&c:x=s[i++]||"",i=0)

Saved 1 byte thanks to @Neil!

Explanation

Works with hashes in the input string and retains trailing white-space after the input string has finished.

var solution =

(s,m)=>
  m.replace(x=/[^]/g,c=> // for each character c of the mold, initialise x to true
    c-1?                 // if c is a space or newline:
      x&&c               // if x is truthy, return c
                         // else if the string has ended, x will equal "" (false), return x
    :                    // else if c is a hash:
      x=                 // set x to the character of the input string
        s[i++]||"",      // return the input string character (or "" if finished)
    i=0                  // initialise i to 0
  )
<input type="text" id="input" value="This probably won't look good." /><br>
<textarea id="mold" rows="6" cols="40">### ### ### ###
# # # # #   #
### ### #   # #
#   #   #   # #
#   #   ### ###</textarea><br>
<button onclick="result.textContent=solution(input.value,mold.value)">Go</button>
<pre id="result"></pre>

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Nice algorithm, but m.replace(/./g,c=>...) is shorter. \$\endgroup\$
    – Neil
    Commented Feb 8, 2016 at 10:44
  • \$\begingroup\$ @Neil You're right. I was trying too hard for it to be different to your answer haha! \$\endgroup\$
    – user81655
    Commented Feb 8, 2016 at 10:49
  • 1
    \$\begingroup\$ Not any more, since you can use /[^]/ instead of /.|\n/. (Also apologies for wrongly suggesting /./.) \$\endgroup\$
    – Neil
    Commented Feb 8, 2016 at 19:23
3
\$\begingroup\$

Python 3, 69 68 67 bytes

def f(s,m):s=iter(s);return''.join(n<'#'and n or next(s)for n in m)

Ideone

Thanks to FryAmTheEggman, Chiel ten Brinke for the byte off. Alternatively, I could have used Python 2 for an extra one (print without ()).

\$\endgroup\$
1
  • \$\begingroup\$ You can save one byte by replacing the print with return. \$\endgroup\$
    – chtenb
    Commented Feb 10, 2016 at 17:11
2
\$\begingroup\$

pb, 359 bytes

^w[B!0]{w[B=10]{t[T+1]b[0]}>}<w[T!0]{w[B!0]{<}>^b[T]vw[B!0]{t[B]b[0]^v[B]v<[X]w[B!0]{>}b[T]<[X]^[Y+2]w[B=0]{>}t[B]b[0]>b[T]v}^t[B-1]vw[B=0]{<}}>b[10]t[X]w[X!-2]{w[B!0]{v}<}w[X!T]{b[35]>}^[Y]^<[X]w[B!10]{t[B]b[0]w[T=35]{t[10]}v<[X]w[B!35]{w[B=0]{v<[X]<b[1]}>}b[T]^[Y]^<[X]w[B=0]{>}}<[X+2]w[B=0]{v}w[B!0]{b[0]>}w[Y!-1]{<[X]^w[B!0]{w[B=35]{b[0]}w[B=10]{b[35]}>}}

In pb, input is strictly one dimensional. It doesn't understand that you're drawing a shape with your input, it just sees one long line with some bytes with a value of 10 thrown in there. The first thing this program does is copy all but the first "line" of input onto Y=0, Y=1, etc, to create the shape of the mold.

Something I've noticed a lot in code golf, but especially when golfing esoteric languages, is that you often don't want to have two branches to deal with; you just set yourself up that you do the same thing in either case. The naive way to solve this problem would probably check the length of the string against the number of hashes in the rest of the input and do something depending on the result, because it has to behave differently depending on what gets cut off. But that's a lot of bytes.

Instead, after completing the mold, an extra line is added to the bottom. It is simply n hashes in a row, where n is the length of the string. Now the string is guaranteed to fit! After inserting all the characters of the string, that extra line that was added is unconditionally destroyed. Any leftover hashes in the mold proper are erased as well, and that's the necessary output!

Of course, it would violate the spec to simply destroy all hashes. After all, there could be a hash in the input string! To handle this, I refer to another part of the spec:

You are given a single printable ASCII string containing no newlines

(Emphasis mine.) By the time we're dealing with the string, we don't really care if there are newlines in it, but we do know that there aren't any. So, all hashes are replaced with newlines before being put into the mold! After all hashes are destroyed, all newlines are replaced with hashes again. This doesn't turn the entire output into a single hash-delimited line because the nature of pb's 2D output means that it never actually put a newline at the end of each line, it just went on to the next line.

Ungolfed:

# Start by copying down the mold
^
# (B means "the character under the cursor")
w[B!0]{       # While B isn't a null byte:
    w[B=10]{    # While B IS a newline:
            t[T+1]    # Increase T by 1
                      # (`T` is the only variable that can be modified directly)
            b[0]      # Overwrite with 0 to break out of inner loop
    }
    >           # Move to the right
                # (dodge the 0 we wrote and progress towards the end of input)
}

# Brush is now at the end of the input, T contains number of lines

<             # Make sure the brush is actually /on/ the input
w[T!0]{       # While T isn't 0:
    w[B!0]{<}>  # Go to the first character of the last line
    ^b[T]       # Place a flag above current character
                # Also a convenient way to get the value of T back later
    vw[B!0]{    # While the character under the flag isn't 0:
            t[B]b[0]  # Put it in T, overwrite with 0
            ^v[B]v    # Go down by the amount written in the space above
            <[X]      # Go left by the amount right the brush is (i.e. go to X=0)
            w[B!0]{>} # Find first empty space
            b[T]      # Write the value of T
            <[X]      # Go left by the amount right the brush is
            ^[Y+2]    # Go up by the amount down the brush is plus 2 (above input)
            w[B=0]{>} # Find flag
            t[B]b[0]  # Pick it up, overwrite with 0
            >b[T]     # Place it to the right
    v}
    ^t[B-1]v    # Collect flag - 1
    w[B=0]{<}   # Go to end of previous line
}

# Mold is placed, all that's left is placing the string
>b[10]        # Put a newline at the end, guaranteed to not be in the string
t[X]          # Save current X value in T

# Add more hashes, guaranteed to fit the input and findable later
w[X!-2]{       # While X!=-2:
    w[B!0]{v}    # Move down until hitting a null byte
    <            # Move left
}
w[X!T]{        # While not at the X value we saved earlier:
    b[35]>       # Travel right, leaving hashes
}

^[Y]^<[X]     # Go to (0, -1)

w[B!10]{      # Until hitting the newline at the end:
    t[B]b[0]    # Pick up character, overwrite with 0
    w[T=35]{    # If it's a hash...
            t[10]     # Make it a newline so we remember, deal with it later
    }
    v<[X]       # Go to (0, 0)
    w[B!35]{    # While B is not a hash:
            w[B=0]{   # While B IS null:
                    v       # Go down
                    <[X]<   # Go to X=-1
                    b[1]    # Print a 1 to break loop (it won't be rendered anyway)
            }
            >           # Go right, either ignore a non hash or go to X=0
    }
    b[T]        # Overwrite hash with picked up character
    ^[Y]^<[X]   # Go to (0, -1)
    w[B=0]{>}   # Go to first character of it to restart loop
}

<[X+2]        # Go to (-2, -1)
w[B=0]{v}     # Go down until finding the row of added hashes
w[B!0]{b[0]>} # Wipe it out unconditionally
w[Y!-1]{      # For every remaining line on the screen:
    <[X]^       # Go to the beginning
    w[B!0]{     # For each character in it:
            w[B=35]{  # If it's a hash:
                    b[0]    # Destroy it
            }
            w[B=10]{  # If it's a newline:
                    b[35]   # Write a hash (after the check to destroy hashes!)
            }
    >}
}
\$\endgroup\$
1
  • \$\begingroup\$ Nice, that looks like a lot of work. \$\endgroup\$
    – Riker
    Commented Feb 8, 2016 at 15:17
1
\$\begingroup\$

ES6, 59 bytes

(t,m)=>m.replace(/#/g,h=>t[i++]||h,i=0).replace(/#[^]*/,'')

70 bytes if the text can contain hashes:

(t,m)=>m.replace(/#/g,(_,n)=>t[i]&&(j=++n)&&t[i++],i=0,j=0).slice(0,j)
\$\endgroup\$
2
  • \$\begingroup\$ Do not remove trailing whitespace, exactly replicate the mold, with exactly the input string replacing the hash characters. \$\endgroup\$
    – orlp
    Commented Feb 8, 2016 at 10:11
  • \$\begingroup\$ @orlp Thanks I'll edit that version back out again. \$\endgroup\$
    – Neil
    Commented Feb 8, 2016 at 10:16
1
\$\begingroup\$

Perl, 53 51 42 + 2 = 44 bytes

@a=/./g;$/="";$_=<>;s/#/shift@a/ge;s/\s+$//

Requires -p to run. Explanation:

@a=/./g; # Split first line into an array of characters
$/=""; # Enable slurp mode (read the rest of lines in one go)
$_=<>;
s/#/shift@a/ge;
s/\s+$//
# With '-p' auto print is enabled
\$\endgroup\$
2
  • \$\begingroup\$ I get some ugly “1”s at the beginning of the output lines. Try this for a clean output: $a=<>;$/="";say<>=~s/#/substr$a,$i++,1/ger \$\endgroup\$
    – manatwork
    Commented Feb 8, 2016 at 10:59
  • \$\begingroup\$ @manatwork I realized that as well, clever with the use of $/ instead of join \$\endgroup\$ Commented Feb 8, 2016 at 11:08
1
\$\begingroup\$

Jelly, 10 8 bytes

¹ƈ<”#$?€

Try it here!

\$\endgroup\$
1
  • 3
    \$\begingroup\$ This seems to print too much trailing whitespace when the input line is shorter than the number of # in the input. \$\endgroup\$ Commented Feb 8, 2016 at 14:34
1
\$\begingroup\$

Perl 6, 72 bytes

my@a=get.comb;say(S:g/\#/{@a.shift//''}/~~{S/\s+$//}),@a||last for lines
\$\endgroup\$
1
\$\begingroup\$

ES6, 47 bytes

Probably the most straightforward solution.

(S,R)=>(i=-1,S.replace(/#/g,_=>R[++i]||R[i=0]))

This code creates an anonymous function that receives 2 parameters and returns the final result.

The first parameter S is the "map" string with your "#", while the second parameter R is the "replacement" for those "#".

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

Ruby, 52 bytes

->a,b{i=-1
a.gsub(/(#)|./){b[i+1]?$1?b[i+=1]:$&:""}}

Attempt This Online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ @KevinCruijssen Thanks for the heads-up. I've updated my answer. \$\endgroup\$
    – Jordan
    Commented Nov 3, 2022 at 15:03
  • \$\begingroup\$ Looking good now, +1 from me. \$\endgroup\$ Commented Nov 3, 2022 at 15:20
1
\$\begingroup\$

Julia 1.0, 98 88 77 bytes

!S=((a,b)=split(S,'
';limit=2);j=0;[b...].|>m->(print(m=='#' ? a[j+=1] : m)))

Try it online!

-22 MarcMush

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I think you can save ~10 bytes by using (a,b)=split(S,'\n';limit=2) \$\endgroup\$
    – MarcMush
    Commented Nov 8, 2022 at 21:54
  • \$\begingroup\$ -11 bytes by starting j at zero and using a[j+=1] (maybe even more) \$\endgroup\$
    – MarcMush
    Commented Nov 11, 2022 at 20:42
1
\$\begingroup\$

K (ngn/k), 39 bytes

{(w@l)#@[y;l#w;:;(l:(#x)&#w:&"#"=y)#x]}

Try it online!

Explanation:

{(w@l)#                                 / up to the final index
       @[y;                             / replace the mold
           l#w;:;                       / at the first l indices of hash characters
                 (l:(#x)&#w:&"#"=y)     / where l is the min of
                                          number of such indices and length of string
                                   #x]} / with the first l characters of string

Uses the fact that one past the last index of a list is null and taking the first null characters defaults to the full list.

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

Python 3

152 127 bytes

A full program.

from sys import stdin as S
s=list(S.readline())
print(''.join([''if not s else(s.pop(0)if m=='#'else m)for m in S.read()]))

106 bytes

A function that takes the stream as input.

def f(S):s=list(S.readline());return''.join([''if not s else(s.pop(0)if m=='#'else m)for m in S.read()])
\$\endgroup\$
3
  • \$\begingroup\$ We already have a Python answer which is much shorter and uses the same method to construct the output. \$\endgroup\$
    – user45941
    Commented Feb 9, 2016 at 8:31
  • \$\begingroup\$ I see. I wrote it yesterday though, when that answer wasn't there yet. Sorry for posting so late \$\endgroup\$
    – chtenb
    Commented Feb 9, 2016 at 8:32
  • \$\begingroup\$ You're not posting late, lots of people probably haven't seen this question yet (I certainly didn't until I saw this post) \$\endgroup\$
    – Blue
    Commented Feb 9, 2016 at 12:19
0
\$\begingroup\$

05AB1E, 12 bytes

`'ÿ«)'#s.;'ÿ¡н

Also complies to the two rules in the comments, unlike some of the other answers:

  1. The input-sentence can contain hashes and (potentially trailing) spaces.
  2. The output does not contain trailing spaces (unless the input contained trailing spaces), only a single trailing newline.

Try it online.

Explanation:

I take advantage of the fact that the input only contains printable ASCII.

`               # Push the characters of the first (implicit) input-sentence separately
                # to the stack
 'ÿ«           '# Append an "ÿ" to the last character
    )           # Wrap the entire stack into a list
     '#        '# Push string "#"
       s        # Swap so the list is at the top again
        .;      # Replace every first "#" in the second (implicit) multi-line string
                # with the items in the list one by one
          'ÿ¡  '# Split the resulting string on "ÿ"
             н  # Only keep the first part
                # (after which the result is output implicitly with trailing newline)

Unfortunately the legacy version of 05AB1E doesn't vectorize with builtin .;, otherwise the second 'ÿ could have been replaced with Z (maximum character - based on codepoint - without popping). In the new 05AB1E version, the min/max builtins doesn't work on characters. But because it doesn't vectorize, it's 15 bytes instead: `'ÿ«)v'#y.;}Z¡н - try it online.

\$\endgroup\$
2
  • \$\begingroup\$ Does this mean the string can’t contain "ÿ"? \$\endgroup\$
    – doug
    Commented Nov 15, 2022 at 15:52
  • \$\begingroup\$ @doug Yes, that's indeed correct. As I mentioned in my answer: the question asks to support printable ASCII, so I take advantage of that with my approach of splitting by a unicode character. \$\endgroup\$ Commented Nov 15, 2022 at 17:32
0
\$\begingroup\$

Python, 64 bytes

f=lambda s,m:m and(z:=m[0]*(m[0]!='#')+s)and z[0]+f(z[1:],m[1:])

Attempt This Online!

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