# Generate Men of Culture

This challenge is inspired by the meme Men of Culture.

The meme involves blanking out parts of the original caption,

Ah, I see you're a man of culture as well.

to make it appear as if the character is saying something else.

Your challenge is to write a program that, given an input, show how the original sentence can be blanked out to achieve the input string.

Rules:

• Use a - character to represent a blanked out character.
• You must not add additional letters to achieve the input string
• You may treat string comparisons as case-insensitive
• You may ignore whitespace in string comparisions
• If no substitution is possible, output a falsy value.
• You may substitute redundant whitespace with a - as well, although not required.
• Where multiple solutions are possible, you may output any of them.

Test cases:

Basic:

Example Meme 1

Ah, I see you're a well.
> Ah, I see you're a --- -- ------- -- well.


Example Meme 2

Ah, I see well.
> Ah, I see ------ - --- -- ------- -- well.


Edge case 1:

What did you just say about me, you little
> false


Edge case 2 (edited):

*no input*
> --- - --- ------ - --- -- ------- -- -----


Intermediate:

Example Meme 3

Ah, I see you're Orwell.
> Ah, I see you're - --- o- -----r- -- well.


Example Meme 4

Ah, ymca.
> Ah, - --- y----- - m-- -- c------ a- ----.


Example Meme 5

Ah, a manual.
> Ah, - --- ------ a man -- -u----- a- --l-.
OR: > Ah, - --- ------ a man -- -u----- a- ---l.


Harder:

Example Meme 6

tea.
> --- - --- ------ - --- -- ---t--e a- ----.


Example Meme 7

eeeee
> --- - -ee -----e - --- -- ------e -- -e---


TL;DR: Given an input string, output a string which represents how the original string should be modified to fit the input string, by using a "-" to represent a blanked out character. If a substitution is not possible, output a falsy value.

Code golf, so shortest code in bytes wins.

Edit: Clarifications

• Ignore whitespace in string comparisions means you can strip away whitespace before you compare strings. For instance, the inputs Ah, a manual and Ah , a manual are treated as equal. Other punctuation , ' . must be preserved. Similarly for output, Ah, a manual is equal to Ah, amanual.

• substitute redundant whitespace refers to the spaces present in the original caption. You don't need to replace them with "-", but if replacing nets you more points then go ahead.

• Your "Orwell" output seems wrong: you've changed an 'f' to an 'r' in the first one. – Draconis Apr 15 '18 at 6:22
• What output should "Ah,<5 SPACES HERE>a manual." yield? – Lynn Apr 15 '18 at 9:53
• If a substitution is not possible, output a falsy value. Well, requiring input validation is highly discouraged. – Erik the Outgolfer Apr 15 '18 at 9:57
• You may treat string comparisons as case-insensitive does that mean we must treat the input as case-insensitive or that we're able to take input in whatever case we want? Also, by You may ignore whitespace in string comparisions, do you mean we must ignore spaces? And what is "redundant whitespace"? – Erik the Outgolfer Apr 15 '18 at 9:59
• I think "input validation," if you could call it that, makes sense here @EriktheOutgolfer – Conor O'Brien Apr 15 '18 at 14:34

# ><>, 94 bytes

"vAh, I see you're a Man of Culture as well.
0/i~ <r
!\:?!^:}=0={:@*:@"-"$?$~}$:@? <>~i+0)?;>o  Try it online! Case-sensitive, doesn't ignore whitespace or punctuation and outputs an empty string if the input is invalid. If you want to try other strings, you can just modify the first line after the "v, as long as it doesn't contain a " or a null byte. # Retina 0.8.2, 117 bytes ^. ¶Ah, I see you're a Man of Culture as well.¶$&
{+i¶(\W|(\w))(.*¶)(?(2)\W*\2)
$1¶$3
}1¶\w
-¶
.*¶.*¶.*\w.*|¶.*¶.*



Try it online! Could save 1 byte by requiring case-sensitivity. Could save 3 bytes by returning --, - --- ---'-- - --- -- ------- -- ----. on empty input. Explanation:

^.
¶Ah, I see you're a Man of Culture as well.¶$&  Prepend the desired text to the input. {+i¶(\W|(\w))(.*¶)(?(2)\W*\2)$1¶$3  Move as many characters from the desired text to the result as possible. If the character is a letter then it also needs to match the next letter in the input, which is then deleted. }1¶\w -¶  If there is no matching letter in the input, change it to a - and try again. .*¶.*¶.*\w.*|¶.*¶.*  If there are still letters left in the input, delete everything, otherwise delete the remainder of the input. # Jelly, 585548 45 bytes “¬²Ẉ,ȷCIbƝɼeỴƤ/ɓIŒ;ṫṚS⁶_ŀỤ ṂB⁾÷ƈ»Ḣ”-1ị⁼ɗ?@€xṆ  Try it online! More readable version: “Ah, I see you're a man of culture as well.”Ḣ”-1ị⁼ɗ?@€xṆ  String compression breakdown: Ah, I{short: see}{short: you}'re a{short: man} of{long: culture} as{short: we}ll.  # Python 2, 126 114 bytes i=input() r='' for c in"Ah, I see you're a man of culture as well.":x=c==i[:1];r+=c*x or'-';i=i[x:] print(i=='')*r  Try it online! # Python 2, 108 106 bytes Input is a list of chars. lambda i:''.join(c==i[2:3]and i.pop(0)or'-'for c in"Ah, I see you're a man of culture as well.")*(i==[])  Try it online! • Could (i=='') not be (i<' ') (using a tab, the lowest printable character)? – Jonathan Frech Apr 16 '18 at 9:06 • @JonathanFrech this is possible, but it is both 7 bytes – ovs Apr 16 '18 at 11:33 • Well, you have got a point there ... – Jonathan Frech Apr 16 '18 at 18:03 # JavaScript (Node.js), 122 120 bytes x=>"Ah, I see you're a Man of Culture as well.".replace(/./g,c=>c>' '?/^(.)\1/i.test(c+x)?(x=x.slice(1).trim,c):'-':c)  Try it online! # Explanation : x => // It takes in 'x' as parameter for function a string "Ah, I see you're a Man of Culture as well.". // What the actual is .replace( // Now we are gonna replace /./g, // selects everything c => // lambda function with param c c > ' ' ? /^(.)\1/i.test( // does it all c + x ) ? // checks if there is a match (x=x.slice(1). // returns everything from 1 to end in an array trim , // removes whitespaces c : '-' : c) // and done  Can be reduced further but replaces whitespaces with '-' as well. If this is acceptable then # JavaScript (Node.js), 112 bytes x=>"Ah, I see you're a Man of Culture as well.".replace(/./g,c=>/^(.)\1/i.test(c+x)?(x=x.slice(1).trim,c):'-')  Try it online! Reduced even further , only replaces whitespaces that are after the given string with '-'. # JavaScript (Node.js), 105 bytes x=>"Ah, I see you're a Man of Culture as well.".replace(/./g,c=>/^(.)\1/i.test(c+x)?(x=x.slice(1),c):'-')  Try it online! • Don't pass What did you just say about me, you little – l4m2 Apr 15 '18 at 15:52 • I'm not getting correct output for your code for the What did you just say about me, you little test case. Your program produces --- - --- ------ - --- -- ------- -- w---- as output which is not what the challenge spec requires. – 0 ' Apr 16 '18 at 6:47 # JavaScript (Node.js), 135 bytes x=>!!x&&(t="Ah, I see you're a Man of Culture as well.".replace(/./g,c=>c>' '?/^(.)\1/i.test(c+x)?(x=x.slice(1).trim(),c):'-':c),!x&&t)  Try it online! If "may" mean either do or not do is okay, then # JavaScript (Node.js), 106 bytes x=>x&&(t="Ah, I see you're a Man of Culture as well.".replace(/./g,c=>c==x[0]?(x=x.slice(1),c):'-'),!x&&t)  Try it online! # Brain-Flak, 764 600 bytes (((<>)))([]((((((([][][]()){}[]){})[][]){}))[[]()])[][]())([[]](([][](([][]){})[]){}())[[]])(([()()][]([[]]([()]([[]](((([()][][][])[]){}[]())[])[]))()()()))[[]])((([[][][]]((([](([()()()][]){})){})(()()()()){}())[[]])[]){})((((()((([][]){}())((()()()){}){})[[][][]]))){}{}())((()(((([]()()()())())){}{}()())[[][]]){}[])(([(()()()){}](((((()()()()){}[]))){}{}))((()()){}()){})(([()][][]([()()()][])))(((([][][]())[([]()()){}()])[]())[[]])([[]]((([]()())(()()()()){}){})()()()){([{}]<>({})){(<{}(((((()()()()())){}{})){}{})>)}{}(<({}<(<()>)<>{({}<>)<>}>{})>)<>{({}<>)<>}{}<>}{}<>{{{}}<>}<>{({}<>)<>}<>  Try it online! Big improvements thanks to Jo King, especially in the string construction but also a few logical tweaks in the main body. Explanation from him It's case-sensitive (so "Ah, I see you're Orwell." doesn't match but "Ah, I see you're orwell." does), whitespace in input is not ignored, and unmatched whitespace in original string is converted to -. By my understanding, all of those are valid options. Explanation: (476 bytes of much improved stack manipulation) #Push string { #While string ([{}]<>({})) #Check whether the top characters are equal {(<{}(((((()()()()())){}{})){}{})>)}{} #If characters are not equal, push - on top of input (<({}<(<()>)<>{({}<>)<>}>{})>)<>{({}<>)<>}{}<> #Take top of input (either - or matched char) and add to output }{} <>{{{}}<>} #Pop both stacks if input is left over <>{({}<>)<>}<> #Reverse output  • You know, there was a question earlier to help automate producing arbitrary test for Brain-Flak. My own submission can (with a couple of modifications) get the text down to 506 bytes – Jo King Apr 17 '18 at 6:12 • With a couple of other improvements, I got the total down to 604 bytes – Jo King Apr 17 '18 at 6:43 • Explanation – Jo King Apr 17 '18 at 6:49 • A nice and round 600 bytes – Jo King Apr 17 '18 at 7:01 • @JoKing you're very good at improving my Brain-Flak it seems – Kamil Drakari Apr 17 '18 at 13:57 # Haskell, 182174172171170 169 bytes import Data.Char t=toLower a!b=(b:)<$>a
""%l=Just$'-'<$l
l@(a:b)%(c:d)|t a==t c=b%d!c|1>0=l%d!'-'
_%_=mempty
(%"Ah, I see you're a man of culture as well.").concat.words


Try it online!

Ungolfed:

import Data.Char

template = "Ah, I see you're a man of culture as well."

-- strip spaces
preprocess :: String -> String
preprocess = filter (/=' ')

-- case-insensitive character comparison
a#b = (toLower a) == (toLower b)

strike' :: String -> String -> Maybe String
strike' "" "" = Just ""  -- base case
strike' _ "" = Nothing   -- chars are exhausted, impossible to convert
strike' "" rem = Just $'-' <$ rem  -- full match, strike rest of chars
strike' cur@(x:xs) (r:rs)
| x # r     =   (r:) <$> strike' xs rs -- character matches; pop a char | otherwise = ('-':) <$> strike' cur rs -- no match; strike char, don't pop

strike :: String -> Maybe String
strike xs = strike' (preprocess xs) template


# Prolog (SWI), 109 bytes

[]+[]+[].
I+[B|X]+[C|O]:-(I=[B|J],B=C;I=J,C=45),J+X+O.
I-O:-I+Ah, I see you're a man of culture as well.+O.


Try it online!

Case-sensitive and whitespace sensitive. The -/2 predicate is the main predicate with its first argument being the input string and the second argument being the output string.

# JavaScript (Node.js), 103 bytes

s=>!s[i=0,r="Ah, I see you're a man of culture as well.".replace(/./g,c=>c==s[i]&&++i||c-1?c:'-'),i]&&r


Try it online!

Case sensitive.

# Pyth, 78 bytesSBCS

V." y°äz ÂµÿéiSs¾ýØC[ócõ!ó5§n"=b.x@zZkIqbN=+kN=hZ.?=+k\-))I<Zlz!z.?k


Test suite
Unprintable characters present in code, see link for correct version.
Case sensitive, does not ignore whitespace.

# Perl 5-F, 192 bytes

@q="Ah, I see you're a man of culture as well."=~/./g;while($x=shift@F){$x=~/\w/||next;while($_=shift@q){push@r,/\W/?$_:/\Q$x/i?$_:'-';$r[-1]=~/\w/i&&last}@q||last}say!$x&&@r,map/\w/?'-':\$_,@q


Try it online!