41
\$\begingroup\$

This challenge is about implementing Shm-reduplication, originating in Yiddish, where one takes a word, duplicates it, and replaces the first syllable in the second word with "Shm" in order to indicate that one does not care. Some examples include:

  • "Isn't the baby cute?", "Eh, baby shmaby"
  • "Come buy from my store, we have a sale!", "Pff, sale shmale"
  • "I got this smartphone yesterday, isn't it cool?", "Meh, smartphone shmartphone"

Rules

In the real world there are a bunch of special cases, but for this challenge we will use rules that describe a simplified version of the full linguistic phenomenon that is more suitable for programming:

  1. Consonants up to first vowel are replaced by "shm".
  2. Prepend shm to words beginning with vowels.
  3. If a word contains no vowels it is returned unchanged. No vowel, no shm.
  4. The vowels are: a, e, i, o, u.
  5. The input will be restricted to lowercase letters.
  6. The output should be a lowercase string containing the reduplicated version of the input. If the input is "string" the output should be "shming".

This is code golf, shortest code wins!

Example solution (ungolfed python)

This is an example of code that would solve the challenge:

def function_shmunction(string):
    vowels = "aeiou"
    for letter in string:
        if letter in vowels:
            index = string.index(letter)
            shming = "shm" + string[index:]
            return shming
    return string

Test cases

  • function -> shmunction
  • stellar -> shmellar
  • atypical -> shmatypical
  • wwwhhhat -> shmat
  • aaaaaaaaaa -> shmaaaaaaaaaa
  • lrr -> lrr
  • airplane -> shmairplane
  • stout -> shmout
  • why -> why

An answer has been accepted since there haven't been any new responses in a while, but feel free to add more!

\$\endgroup\$
9
  • 1
    \$\begingroup\$ I've made a minor edit to your post, since the Zsh answer seems to think you should output the input + a space. If I misunderstood something and my edit is incorrect, feel free to revert it. \$\endgroup\$ Commented May 24, 2022 at 8:41
  • 1
    \$\begingroup\$ @KevinCruijssen No, you're correct. I might have been a bit unclear about that in the text. \$\endgroup\$
    – JSorngard
    Commented May 24, 2022 at 8:43
  • 2
    \$\begingroup\$ @jezza_99 the sandbox actually had the same output format as this post, I believe my formatting of the explanation of the real world phenomenon was done carelessly and so was easy to interpret as the intended output format. \$\endgroup\$
    – JSorngard
    Commented May 24, 2022 at 9:18
  • 17
    \$\begingroup\$ must. resist. changing. sh. to. sch. to. match. local. accent. \$\endgroup\$
    – Joshua
    Commented May 24, 2022 at 17:18
  • 2
    \$\begingroup\$ @phoog The original reason I omitted y was that I am uncertain of its position as a vowel in the English language as a non-native speaker. I agree that some very amusing examples are lost when you ignore y like this, but I do not think it's a good idea to change the rules this far into the challenge. \$\endgroup\$
    – JSorngard
    Commented May 27, 2022 at 13:55

40 Answers 40

12
\$\begingroup\$

sed, 29 bytes

s/[^aeiou]*\([aeiou]\)/shm\1/

Try it online!

\$\endgroup\$
10
\$\begingroup\$

Jelly, 16 12 bytes

œlØḄṭ⁸¹?“shm

Try it online!

-4 thanks to ovs remembering there's a strip builtin

œlØḄ            Strip all leading consonants.
    ṭ   “shm    Prepend "shm"
      ¹?        if there's anything left, otherwise
     ⁸          give the original word.
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Porting Jitse's Python answer gives 14 bytes: œlØḄ“shm”;$⁸Ẹ? \$\endgroup\$
    – ovs
    Commented May 24, 2022 at 10:21
  • \$\begingroup\$ I was about to suggest you post that yourself until I realized what builtin it leans on... :facepalm: \$\endgroup\$ Commented May 24, 2022 at 10:33
10
\$\begingroup\$

Haskell, 50 bytes

snd.break(`elem`"aeiou")>>=(?)
""?s=s
r?_="shm"++r

Try it online!

Thanks to Roman Czyborra for -2 bytes

\$\endgroup\$
1
  • 1
    \$\begingroup\$ 50: span.notElem==break.elem \$\endgroup\$ Commented Jan 14, 2023 at 1:51
9
\$\begingroup\$

Stax, 11 bytes

ÄFï¥░$º{═┘ç

Run and debug it

  1. Left-trim consonants.
  2. If non-empty, prepend "shm".
  3. Else restore original input.
\$\endgroup\$
9
\$\begingroup\$

sed, 25 bytes

/[aeiou]/s/[^aeiou]*/shm/

Try it online!

/[aeiou]/ is a conditional that only runs the substitution s/[^aeiou]*/shm/ if there is a vowel in the line. This prevents needing to capture the first vowel and then using a backreference as in the more obvious s/[^aeiou]*\([aeiou]\)/shm\1/.

\$\endgroup\$
7
\$\begingroup\$

Powershell, 36 bytes

$args-replace('^.*?([aeiou])','shm$1')

Explanation

Simple replace with a named group reference.

+4

Thanks caird coinheringaahing

-5

Thanks mazy

\$\endgroup\$
6
  • 2
    \$\begingroup\$ Welcome to Code Golf, and nice answer! \$\endgroup\$
    – rydwolf
    Commented May 24, 2022 at 22:58
  • 3
    \$\begingroup\$ Welcome to Code Golf! Currently, this answer does not meet our standard rules: 1) this doesn't appear to work unless the input begins with a vowel, and 2) this assumes the input is saved in the $x variable, which is not an acceptable form of input. Both of these can be corrected for +9 bytes \$\endgroup\$ Commented May 24, 2022 at 23:56
  • 2
    \$\begingroup\$ @anothervictimofthemouse You're welcome to use the program I linked to. You can find an answer template on that site if you click the link button, and scroll down to the "Code Golf Answer" option. You can also find formatting tips in the "Answering" post in the Welcome page I linked \$\endgroup\$ Commented May 25, 2022 at 0:14
  • 3
    \$\begingroup\$ Sorry, my bad, I got the regex wrong: it should be ^.*?([aeiou]) in the replacement stage \$\endgroup\$ Commented May 25, 2022 at 1:40
  • 1
    \$\begingroup\$ you can save 5 bytes Try it online! \$\endgroup\$
    – mazzy
    Commented May 25, 2022 at 18:59
6
\$\begingroup\$

Zsh, 36 bytes

<<<${(S)1/#(#b)*([aeiou])/shm$match}

Attempt This Online!

  • <<<: print
  • ${1}: the input...
    • //: replace the first match
      • #: matching only at the beginning of the string
      • (#b): activate backreferences, so the () group gets stored in the $match variable
      • (S): use the shortest possible match, rather than the longest
      • *: anything
      • (): store this match in the variable:
        • [aeiou]: followed by a vowel
    • with shm$match: the string shm, plus the matched vowel

$match is actually an array which contains all the backreference groups, but since there's only one group, we don't need to access any specific element with [1]

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

Python 3.8 (pre-release), 62 bytes

lambda s:(q:=s.lstrip('bcdfghjklmnpqrstvwxyz'))and'shm'+q or s

Try it online!

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

05AB1E, 28 13 bytes

žNSÛ©ai®…shmì

Try it online or verify all test cases.

Explanation:

žNSÛ           # Trim all leading consonants of the (implicit) input-string
    ©          # Store this new string in variable `®` (without popping)
     ai        # Pop, and if any letters are left (thus the input-string contains
               # a vowel):
       ®       #  Push string `®` again
        …shmì  #  Prepend "shm"
               #  (implicitly print it as result)
               # (implicit else)
               #  (implicitly output the implicit input-string)
\$\endgroup\$
6
+150
\$\begingroup\$

Haskell, 48 bytes

g.break(`elem`"aeiou")
g(s,"")=s
g(_,r)="shm"++r

Try it online!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ I forgot about your comment but I would have encouraged you to post an answer so I'm glad you did! Nice find, it's funny how span being shorter than takeWhile or dropWhile encourages you to use both parts even if you can make do with one. \$\endgroup\$
    – xnor
    Commented Jun 2, 2022 at 8:31
6
\$\begingroup\$

Japt, 15 bytes

r"^.*?%v"ÈÌi`¢m

Try it (Includes all test cases)

r"^.*?%v"ÈÌi`¢m     :Implicit input of string
r                   :Replace
 "^.*?%v"           :  RegEx /^.*?[aeiou]/gi
         È          :  Pass each match through a function
          Ì         :    Last character
           i        :    Prepend
            `¢m     :      Compressed string "shm"
\$\endgroup\$
5
\$\begingroup\$

Python, 53 bytes

lambda s:re.sub("^.*?([aeiou])","shm\\1",s)
import re

Attempt This Online!

Another regex answer.


Alternative:

Python, 53 bytes

lambda s:re.sub(".*?(?=[aeiou])","shm",s,1)
import re

Attempt This Online!

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

Vyxal, 13 bytes

k⁰øl:[«88«p|_

Try it Online!

Port of Jelly.

How?

k⁰øl:[«88«p|_
k⁰øl           # Strip leading consonants
    :[         # If there's anything left:
      «88«p    # Prepend "shm"
           |_  # Else, pop, returning the implicit input
\$\endgroup\$
4
\$\begingroup\$

Retina, 19 bytes

Just a regex replacement, there might be some language feature which allows for a shorter solution.

^.*?(?=[aeiou])
shm

Try it online!

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

SNOBOL4 (CSNOBOL4), 49 bytes

	I =INPUT
	I BREAK('aeiou') ='shm'
	OUTPUT =I
END

Try it online!

BREAK "matches zero or more characters provided they are not in the set of characters in the argument string. That is, it matches up to, but not including, a character from the argument string."

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

C (gcc), 81 bytes

i;f(char*s){for(i=0;*s-"aeiou"[++i%6];i%6||s++);printf("shm%s"+3*!*s,s-i*!*s/6);}

Try it online!

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

C (gcc), 125 113 bytes

-8 bytes thanks to @ceilingcat

#define T&&*s-
main(s,v)char**v,*s;{for(s=*++v;*s T'a'T'e'T'i'T'o'T'u'||!(*v=memcpy(s-3,"smh",3));++s);puts(*v);}

Try it online!

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

JavaScript, 36 bytes

s=>s.replace(/.*?([aeiou])/,"shm$1")

Try it online! (includes all test cases)

\$\endgroup\$
2
  • \$\begingroup\$ Why u need the ^? \$\endgroup\$
    – l4m2
    Commented Jan 12, 2023 at 17:59
  • \$\begingroup\$ Possibly a holdover from my Japt solution, @l4m2, where it's cheaper to use ^ than it is to disable the global flag, which is enabled by default. Ping me on Monday to remind me to investigate properly. \$\endgroup\$
    – Shaggy
    Commented Jan 13, 2023 at 20:06
3
\$\begingroup\$

Excel, 149 bytes

=IFERROR(REPLACE(A1,1,FIND("$",SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(A1,"a","$"),"e","$"),"i","$"),"o","$"),"u","$"))-1,"shm"),A1)

102 bytes just to find the vowels. If anybody knows a better way to do this. please share.

From inside out:

  • SUBSTITUTE vowels with $
  • Find the index of the first $
  • Replace chars before this index with shm
  • If no vowels, return input.
\$\endgroup\$
1
  • 2
    \$\begingroup\$ 78 bytes =IFERROR("shm"&MID(A1,MIN(IFERROR(FIND({"a","e","i","o","u"},A1),"")),9^9),A1). 9^9 is well over the 2^15-1 character limit for a cell so it works fine in the MID() function for all valid inputs. \$\endgroup\$ Commented May 25, 2022 at 13:44
3
\$\begingroup\$

Perl 5 + -p, 20 bytes

Uses the ; separator (as ; is implicitly added via -p).

s;.*?(?=[aeiou]);shm

Try it online!


Perl 5 + -lF/^[^aeiou]+/ -M5.10.0, 17 bytes

Slightly more cheaty with the regex in the flags, but saves a few bytes

say@F?(shm,@F):$_

Try it online!

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

brainfuck, 531 bytes

->+[->[>],[+[-<+]->+[>]<[>+>+<<-]>>[<<+>>-]-[>++<-----]>-----<<[->>-<<]+>>[<<->>[-]]<<[+[-<+]->-]+[-<+]->[[>]<[>+>+<<-]>>[<<+>>-]-[>++<-----]>-<<[->>-<<]+>>[<<->>[-]]<<[+[-<+]->-]+[-<+]->[[>]<[>+>+<<-]>>[<<+>>-]-[>++<-----]>+++<<[->>-<<]+>>[<<->>[-]]<<[+[-<+]->-]+[-<+]->[[>]<[>+>+<<-]>>[<<+>>-]-[>--<-------]>+<<[->>-<<]+>>[<<->>[-]]<<[+[-<+]->-]+[-<+]->[[>]<[>+>+<<-]>>[<<+>>-]----[>+++++<--]>-<<[->>-<<]+>>[<<->>[-]]<<[+[-<+]->-]+[-<+]->[>]]]]]]+[-<+]->]>[>]<-[++[-<+]->>[.>]>-<]>+[[--------->++<]>+.-----------.+++++.<<<.,[.,]]

Try it online!

This implementation is as close to a nested if/else statement as bf allows. Simply checks each letter to see if it's a vowel. If it finds one, it prints "shm", then the vowel, then the rest of the input. If it doesn't, it simply prints out the input from its buffer.


brainfuck, 423 bytes

+[--------->++<]>+.-----------.+++++.<->>+[>,[>+>+<<-]>>[<<+>>-]-[>++<-----]>-----<<[->>-<<]+>>[<<->>[-]]<<[<<->>-]<<[>[>+>+<<-]>>[<<+>>-]-[>++<-----]>-<<[->>-<<]+>>[<<->>[-]]<<[<<->>-]<<[>[>+>+<<-]>>[<<+>>-]-[>++<-----]>+++<<[->>-<<]+>>[<<->>[-]]<<[<<->>-]<<[>[>+>+<<-]>>[<<+>>-]-[>--<-------]>+<<[->>-<<]+>>[<<->>[-]]<<[<<->>-]<<[>[>+>+<<-]>>[<<+>>-]----[>+++++<--]>-<<[->>-<<]+>>[<<->>[-]]<<[<<->>-]]]]]+[-<+]->>]>.,[.,]

Try it online!

A shorter version that only works for words with vowels.

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

Charcoal, 25 bytes

≔⌕Eθ№aeiouι¹η¿⊕η«shm✂θη»θ

Try it online! Link is to verbose version of code. Explanation:

≔⌕Eθ№aeiouι¹η

Count the number of vowels in each character and find the first 1 i.e. the index of the first vowel in the input.

¿⊕η

If there was in fact a vowel, then...

«shm✂θη»

... output the literal string shm followed by the input sliced starting at that index.

θ

Otherwise just output the input string.

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

Java 8, 40 bytes

s->s.replaceAll("^.*?([aeiou])","shm$1")

Port of the JavaScript and Retina answers.

Try it online.

Or a minor alternative:

s->s.replaceAll("^.*?(?=[aeiou])","shm")

Try it online.

Explanation:

s->             // Method with String as both parameter and return-type:
  s.replaceAll( //  Modify and return the String: Regex-replace all
    "...",      //  these matches
    "...")      //  with these replacements

Regex-explanation 1:

^.*?([aeiou])    # Match:
^                #  At the start of the string
 .*              #  Match zero or more characters
   ?             #  Which are optional, to give other matches precedence
     [aeiou]     #  Followed by a vowel
    (       )    #  captured in capture group 1

shm$1            # Replacement:
shm              #  Literal "shm"
   $1            #  And the vowel of capture group 1

Regex-explanation 2:

^.*?([aeiou])    # Match:
^                #  At the start of the string
 .*              #  Match zero or more characters
   ?             #  Which are optional, to give other matches precedence
    (?=       )  #  Followed by a positive (non-matching) look-ahead to:
       [aeiou]   #   A vowel

shm              # Replacement:
shm              #  Literal "shm"

Minor note: the replaceAll with ^ is basically the same as a replaceFirst without the ^, but 1 byte shorter: try it online.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Java is shorter than Python. What is going on... \$\endgroup\$
    – Romanp
    Commented May 24, 2022 at 23:12
  • \$\begingroup\$ It's really a regex solution :-) \$\endgroup\$
    – toolforger
    Commented May 27, 2022 at 12:30
2
\$\begingroup\$

Pip, 15 bytes

a~XVaH$(:"shm"a

Attempt This Online!

Explanation

a~XVaH$(:"shm"a
a                Command-line argument
 ~               Find first match of
  XV             regex `[aeiou]`
      $(         Index of that match
    aH           Prefix of cmdline arg containing that many characters
        :        Set to
         "shm"   that string
                 If a vowel was not found, $( is nil, which means no assignment is done
                 and a's value remains unchanged
              a  Autoprint the (possibly changed) value of a
\$\endgroup\$
2
\$\begingroup\$

APL (Dyalog Extended), 31 bytes

{⍵≢⍛≡n←⌊/⍵⍳'aeoiu':⍵⋄'shm',n↓⍵}

Try it online!

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

Haskell, 58 57 bytes

f s|g s>""="shm"++g s|1>0=s
g=dropWhile(`notElem`"aeiou")

Attempt This Online!

-1 byte thanks to Wheat Wizard ♦

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

GeoGebra, 114 bytes

s="a"
InputBox(s)
S=Take(s,IndexOf(Element(Split(s,Split("bcdfghjklmnpqrstvwxyz",{""})),1),s))
If(S=="",s,"shm"+S)

Not sure why, but the code won't work if you put in an empty string as initial value of s (or any string consisting of only consonants), but it will work properly for all test cases (even ones that do consist of only consonants) if you have a string with a vowel as the initial value of s.

The input should be entered into the Input Box.

Try It On GeoGebra!

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

V (Eh, vim shmim), 23 bytes

:%s/.\{-}\ze[aeiou]/shm

vim non-greedy regex with look-ahead.

Try it online!

Same in “magic very very” mode:

23 bytes

:%s/\v.{-}[aeiou]@=/shm

Try it online!

Further 3 bytes can be saved by replacing :%s/ with V’s specific í

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

Go, 103 bytes

import."regexp"
func f(s string)string{return MustCompile(`^.*?([aeiou])`).ReplaceAllString(s,"shm$1")}

Attempt This Online!

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

tinylisp 2, 64 61 bytes

(\(S)(: T(drop-while(. !(p contains?"aeiou"))S)(? T(,"shm"T)S

Try it at Replit. Example session:

tl2> (\(S)(: T(drop-while(. !(p contains?"aeiou"))S)(? T(,"shm"T)S
(() (S) (: T (drop-while (. ! (p contains? "aeiou")) S) (? T (, "shm" T) S)))
tl2> (def shm _)
shm
tl2> (map shm (list "codegolf" "stellar" "airplane" "lrr"))
("shmodegolf" "shmellar" "shmairplane" "lrr")

Explanation

Port of Unrelated String's Jelly answer, among others.

First, we need a function that tests whether a character is not a vowel:

(. !(p contains?"aeiou"))
(.                      ) ; Compose
   !                      ; Logical negation
    (p                 )  ; with the partial application of
       contains?          ; the contains? function
                "aeiou"   ; to "aeiou"

Then our main function is as follows (where (...) represents the above function):

(\(S)(: T(drop-while(...)S)(? T(,"shm"T)S)))
(\                                         ) ; Lambda function
  (S)                                        ; that takes a string S:
     (: T                                 )  ;  In what follows, let T be
         (drop-while     S)                  ;   Drop characters from S while
                    (...)                    ;   they are not vowels
                           (? T          )   ;  Is T truthy (nonempty)?
                               (,"shm"T)     ;  If so, concatenate "shm" with T
                                        S    ;  If not, return the original string S
\$\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.