46
\$\begingroup\$

Posted from here.

This challenge is highly "distilled" from this question. Special thanks to @Akababa!

In this task, you should insert an exclamation mark at the start of the string and after every character.

Rules

  • There will always be a non-empty-string input. The input will not contain tabs either. You can assume that the input only contain non-extended ASCII printable characters and newlines.
  • The input will not contain trailing newlines as long as your language can't detect a newline.
  • This is a contest; the shortest answer should win.

Examples

  • 4 newlines result in 5 newline-delimited exclamation marks. It is very hard to put this as a Markdown text, so this is stated instead.
1 2 3 4 5 6
129591 129012 129127 129582

0

Outputs

!1! !2! !3! !4! !5! !6!
!1!2!9!5!9!1! !1!2!9!0!1!2! !1!2!9!1!2!7! !1!2!9!5!8!2!
!
!0!
asd afjoK ak:e
kPrLd
    fOJOE;
    KFO
KFkepjgop sgpaoj   faj

Outputs

!a!s!d! !a!f!j!o!K! !a!k!:!e!
!k!P!r!L!d!
! ! ! ! !f!O!J!O!E!;!
! ! ! ! !K!F!O!
!K!F!k!e!p!j!g!o!p! !s!g!p!a!o!j! ! ! !f!a!j!

A base test case with only one character:

a

Outputs

!a!

(Auto-completion! Just kidding, there is no such thing.) Contains exclamation marks:

!!
!!
!!
!!
!!

Outputs:

!!!!!
!!!!!
!!!!!
!!!!!
!!!!!
\$\endgroup\$
12
  • 7
    \$\begingroup\$ very similar question \$\endgroup\$
    – Giuseppe
    Commented Aug 18, 2019 at 11:06
  • 9
    \$\begingroup\$ I really don't understand the downvote - this is a clear and well written challenge. Re: being a duplicate - it's not (preceding '!' makes for a big difference), and I don't believe anyone has suggested so (no close votes). \$\endgroup\$ Commented Aug 18, 2019 at 13:45
  • 1
    \$\begingroup\$ if a language can't tell the difference between a\n and a, can we require that there are no trailing newlines? \$\endgroup\$
    – Giuseppe
    Commented Aug 18, 2019 at 14:29
  • 31
    \$\begingroup\$ Downvotes are inserted between every upvote, just like what the challege describes. \$\endgroup\$
    – user85052
    Commented Aug 18, 2019 at 14:34
  • 1
    \$\begingroup\$ Is the case of a single space input " ", is the output supposed to be "!" or "! !" \$\endgroup\$
    – Kai
    Commented Aug 19, 2019 at 3:52

97 Answers 97

2
\$\begingroup\$

Javascript (27 bytes)

My first code golf, 27 bytes in Javascript. Could probably shave some more bytes off, but I'm not too sure.

f={x:s=>`!${s.join('!')}!`}

Example Usage

console.log(f.x('1 2 3 4 5'.split('')))
// Output: !1! !2! !3! !4! !5!
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Welcome to CCGC! Using the way of defining lambdas that has been kind of standardized on this site, this is 21 bytes: Try it online! (unless the lambda is called recursively, the f= does not need to be counted) \$\endgroup\$
    – Stephen
    Commented Dec 25, 2019 at 3:58
2
\$\begingroup\$

1+, 20 19 bytes

1##11"+""*"**+;,;1#

1+ 19 vs 18 MAWP

Error-terminating because comparison is expensive.

\$\endgroup\$
8
  • \$\begingroup\$ I think i'm winning for now ;) btw, mawp submissions should be here github.com/8Dion8/8Dion8.github.io/blob/master/scraper/… \$\endgroup\$
    – Dion
    Commented Aug 12, 2020 at 8:20
  • \$\begingroup\$ @Dion Yeah, only 1 byte away! I'm creating the 1+ answer list now. \$\endgroup\$ Commented Aug 12, 2020 at 8:32
  • \$\begingroup\$ I created a python script to gather everything... Maybe you could change it a bit and use it for gathering 1+ answers? If you are interested, ill clean up the code so its understandable xd \$\endgroup\$
    – Dion
    Commented Aug 12, 2020 at 8:51
  • \$\begingroup\$ @Dion Apparently your script searches for 1+ with the SE search tool but that will not work well for 1+. Manual 1+ answer list \$\endgroup\$ Commented Aug 12, 2020 at 10:58
  • \$\begingroup\$ github.com/8Dion8/8Dion8.github.io/blob/master/scraper/… is the current script \$\endgroup\$
    – Dion
    Commented Aug 12, 2020 at 11:12
2
\$\begingroup\$

Zsh, 12 bytes

<<<${1///!}!

Try it online!

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

K (ngn/k), 13 12 bytes

-1 byte from @ngn's savings

{x,/y,'x}"!"

Try it online!

Creates a function projection, with x fixed to "!".

  • y,'x pair-wise append an exclamation mark to each character in the input
  • x,/ flatten the list, using "!" as the seed (to prepend the leading "!")
\$\endgroup\$
1
  • 1
    \$\begingroup\$ save a byte by turning "!" into a curried argument: f:{x,/y,'x}"!" \$\endgroup\$
    – ngn
    Commented Feb 12, 2021 at 19:05
2
\$\begingroup\$

C (gcc), 48 45 39 bytes

f(char*s){printf("!%.1s",s++)>1&&f(s);}

Try it online!

-3 thanks to ceilingcat

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

Python, 30 Bytes

lambda x:'!%s!'%'!'.join([*x])

It feels like these methods were designed for the challenge!

-1 from Jacob (now noodle man) by using the cursed % (Dun dun dun!)

-3 from Glorfindel for using a starred method for conversion!

!T!r!y! !r!u!n!n!i!n!g! !i!t! !o!n!l!i!n!e!

\$\endgroup\$
3
  • \$\begingroup\$ Here's 33, I don't know much python so it can likely be golfed further \$\endgroup\$ Commented May 29, 2023 at 14:07
  • \$\begingroup\$ list(...) can always be [*...] instead \$\endgroup\$
    – Jo King
    Commented May 30, 2023 at 13:24
  • 1
    \$\begingroup\$ 27 bytes - you don't even need to convert it to a list, since any iterable will work. \$\endgroup\$
    – The Thonnu
    Commented May 30, 2023 at 14:53
2
\$\begingroup\$

Rockstar, 67 bytes

listen to S
while S
cut S
join S with "!"
say "!"+S+"!"
listen to S

Try it here (Code will need to be pasted in)

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

Python 3, 29 Bytes

print('',*input(),'',sep="!")

Try It Online

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

Charcoal, 6 bytes

⭆S⁺!ι!

Try it online! Link is to verbose version of code. Works on empty strings too. Input format is somewhat cumbersome due to Charcoal's lack of EOF. Works by preceding each character with a ! and then suffixing a final ! on the end. Alternative version, also 6 bytes:

⪫!!⪫S!

Try it online! Link is to verbose version of code. Works by joining the characters on ! and then wrapping them in !!.

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

SNOBOL4 (CSNOBOL4), 94 bytes

I	I =INPUT	:F(END)
S	I LEN(1) . X REM . I	:F(O)
	O ='!' O X	:(S)
O	OUTPUT =O '!'
	O =	:(I)
END

Try it online!

Prints with an additional trailing newline (as SNOBOL always prints a line break). The way input is consumed, there is no way of distinguishing between a final line ending in \n or not.

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

Stax, 6 5 bytes

_z'!R

Run and debug it

Replace "" with "!" using regex replacement. I don't exactly understand why this works.

Edit: Found it in the Ecma spec: 15.5.4.10

If there is a match with an emptystring (in other words, if the value of regexp.lastIndex is left unchanged), increment regexp.lastIndex by 1.

Old Stuff:

I would have been able to get to 5 bytes in either of two scenarios.

  1. If input was provided in an escaped literal e.g. "line1\nline2". But I opted against that for the sake of "usability".
  2. If there was not a bug feature in stax's zip implementation when encountering empty strings/arrays.
\$\endgroup\$
1
\$\begingroup\$

Wolfram Language (Mathematica), 49 48 42 bytes

#~StringSplit~""~StringRiffle~{a="!",a,a}&

Try it online!

-6 bytes thanks to @attinat

\$\endgroup\$
2
  • \$\begingroup\$ The code in the Header, Code, and Footer sections is run. You can use infix notation and drop the { } in StringSplit for 42 bytes \$\endgroup\$
    – att
    Commented Aug 19, 2019 at 23:24
  • \$\begingroup\$ @attinat Thanks that helps a lot! \$\endgroup\$
    – Kai
    Commented Aug 20, 2019 at 19:50
1
\$\begingroup\$

Ahead, 12 bytes

~irj!'~
@Wu<

Try it online!

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

Lua, 31 bytes

print((io.read():gsub("","!")))
\$\endgroup\$
1
\$\begingroup\$

C (gcc), 32 bytes

f(s){printf("!%s",s)-1&&f(s+4);}

Try it online!

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

Red, 47 bytes

func[s][parse s[insert"!"any[skip insert"!"]]s]

Try it online!

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

C#, 142 bytes

public class P{public static void Main(string[]a){System.Console.Write("!");foreach(char c in a[0]){System.Console.Write(c.ToString()+"!");}}}
\$\endgroup\$
0
1
\$\begingroup\$

Pip, 5 bytes

aJW'!

Try it online!

The JW builtin was made for challenges like this.

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

Branch, 11 bytes

33.,[.33.,]

Try it on the online Branch interpreter!

Put 33 on the tree and output (!). Then, grab input. Finally, while that value is not EOF, output it, output 33 (!), and grab input again.

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

Vim, 13 bytes

:%s/\_./!&/g

Works by putting a ! before every character, including newline characters. The TIO version doesn't work properly for the 4 newline testcase, but it does work in Vim.

Try it online!

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

BRASCA, 14 13 bytes

-1 byte thanks to RezNesX

,![$'!oo{]'!o

Try it online!

Explanation

,               - Reverse stack
 ![$    {]      - Loop stack length:
    '!oo        -     Print "!" followed by the next letter
          '!o   - Print the last "!"
\$\endgroup\$
1
  • 1
    \$\begingroup\$ 13 bytes: ,![$'!oo{]'!o \$\endgroup\$
    – RezNesX
    Commented May 12, 2021 at 11:20
1
\$\begingroup\$

Subleq (8-bit), 1211 bytes

-1 byte for removing last 0

2 -1 33
-1 8 -1
8 -1 0
8 8 

Subleq emulator

Explanation

0:  2 -1 33 ' Output 2: (char(33)); 3rd argument is not used for output so use it for memory
3: -1  8 -1 ' Read input to 8:, exit if null
6:  8 -1  0 ' Output 8:
9:  8  8    ' 8: = 0 goto 0
\$\endgroup\$
1
\$\begingroup\$

Go, 105 bytes

import."regexp"
func f(s[]byte)[]byte{return append(MustCompile(`(?s).`).ReplaceAll(s,[]byte(`!$0`)),33)}

Attempt This Online!

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

Excel, 44 bytes

="!"&CONCAT(MID(A1,SEQUENCE(LEN(A1)),1)&"!")
  • "!" is just the first !.
  • CONCAT(MID(A1,SEQUENCE(LEN(A1)),1)&"!")
    • SEQUENCE(LEN(A1)) creates an array 1, 2, ... X where X is the length of the input.
    • MID(A1,SEQUENCE(~),1) pulls the nth character from the input.
    • MID(~)&"!" adds ! after every one of those characters.
    • CONCAT(MID(~)&"!") combines all those nth character + ! into one string.

Screenshot

Note: The line breaks are there with or without Word Wrap turned on but it won't look right until you turn it on. The screenshot has Word Wrap turned on.

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

Factor,  31  28 bytes

[ 33 interleaved [I !${}!I]]

Attempt This Online!

  • 33 interleaved Insert an exclamation point between each character of the input.

  • [I !${}!I] Interpolate the above string into the ${}, adding exclamation points to the beginning and end, and print.

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

BQN, 11 bytes

'!'⊸(⊣∾´∾¨)

Anonymous tacit function that takes and returns a string. Try it at BQN online!

Explanation

'!'⊸(⊣∾´∾¨)
    (      )  Call the following function with the original argument on the right
'!'⊸          and '!' on the left:
         ∾¨     Concatenate each (prepends '!' to each character, resulting
                in a list of two-character strings)
       ∾´       Right-fold that list on concatenation
     ⊣          with a starting value of the left argument (i.e. '!')

A port of Sʨɠɠan's APL solution is also 11 bytes:

(∾⊢∾∾¨)⟜'!'

Try it!

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

ARM Thumb machine code, 12 bytes

21 22 08 c8 0c c1 00 2b fb d1 70 47

Assembly source:

    .syntax unified
    .arch armv7-a
    .thumb
    .thumb_func
    .globl insert_between
// input: r0: pointer to null terminated UTF-32LE string
//        r1: pointer to buffer
// output: null terminated UTF-32LE string at *r1
// C callable prototype:
//   void insert_between(const char32_t *in, char32_t *out);
insert_between:
    // Put '!' in a register for later
    movs   r2, #'!'
.Lloop:
    // Load char from pointer, advance pointer
    ldmia  r0!, {r3}                          @ tmp = *in++;
    // Store '!' then the char from the pointer.
    // The null terminator will be included,
    // which also adds the trailing '!'.
    stmia  r1!, {r2, r3}                      @ *out++ = '!', *out++ = tmp;
    // Loop if r3 wasn't a null terminator
    cmp    r3, #0
    bne    .Lloop
    // return
    bx     lr

Callable from C with the following prototype:

void insert_between(const char32_t *in, char32_t *out);

As with most of my Thumb string solutions, everything is null terminated UTF-32 thanks to ldmia and stmia being the only narrow instructions to load and advance a pointer.

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

C, 42 bytes

f(char *s){printf("!%c",*s);if(*s++)f(s);}

Essentially to not have to have two printf statments I have the printf run on the null byte of the string which prints the '!' but the null byte is ignored.

Easier to read

f(char *s){
  // Prints ! and char of string
  printf("!%c", *s);
 
  // If more string than recurse for next char
  if(*s != 0) f(s+1);
}
\$\endgroup\$
1
  • \$\begingroup\$ I don't know much C, would removing that space be valid? \$\endgroup\$
    – rydwolf
    Commented Jun 9, 2023 at 5:27
1
\$\begingroup\$

(,) 111 91 Chars or \$91\log_{256}(3)\approx18.03\$ Bytes

((),()()()()()()()())((),(())(())(())(())())(,,,(()()),(,(()(),((()()())),,(())))(()()),())

TIO

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

Marbles, 774 bytes

An elegant 25 x 31 grid of 774 characters:

○══════════════════════╗
║○═══════════════════╗ ║
║║○════════════════╗ ║ ║
║║║○═════════════╗ ║ ║ ║
║║║║○══════════╗ ║ ║ ║ ║
║║║║║○═══════╗ ║ ║ ║ ║ ║
║║║║║║○════╗ ║ ║ ║ ║ ║ ║
║║║║║║║○═╗ ║ ║ ║ ║ ║ ║ ║
║║║║║║║║○╜○╜○╜○╜○╜○╜○╜○╜
║║║║║║║║ ┃ ║ ║ ║ ║ ┃ ║ ║
║║║║║║║║◆╢◆╢◆╢◆╢◆╢◆╢◆╢◆╢
║║║║║║║║ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃
║║║║║║║║◇╢◇╢◇╢◇╢◇╢◇╢◇╢◇╢
║║║║║║║║○╬═╬═╬═╬═╬═╬═╬╗║
║║║║║║║║║║╔╬╗║╔╬╗║╔╬╗║║║
║║║║║║║║╓╢╙╢╓╢╙╢╓╢╙╢╓╢╙╢
║║║║║║║║╚╬╝║╚╬╝║╚╬╝║╚╬╝║
║║║║║║║║○╜○╜○╜○╜○╜○╜○╜○╜
║║║║║║║║ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃
║║║║║║║║◇╜◇╜◇╜◇╜◇╜◇╜◇╜◇╜
║║║║║║║║◆╢◆╢◆╢◆╢◆╢◆╢◆╢◆╢
║║║║║║║║ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃
║║║║║║║║◇╢◇╢◇╢◇╢◇╢◇╢◇╢◇╢
║║║║║║║╚═╝ ║ ║ ║ ║ ║ ║ ║
║║║║║║╚════╝ ║ ║ ║ ║ ║ ║
║║║║║╚═══════╝ ║ ║ ║ ║ ║
║║║║╚══════════╝ ║ ║ ║ ║
║║║╚═════════════╝ ║ ║ ║
║║╚════════════════╝ ║ ║
║╚═══════════════════╝ ║
╚══════════════════════╝

Marbles is not available on tio.run yet but the test examples can be run using marbles.py:

± echo test | ./marbles.py exclamation.txt --quiet --no-display
!t!e!s!t!
!

Ungolfed version:

╔══════════════════════════════════════════════════╗
║  ╔════════════════════════════════════════════╗  ║
║  ║  ╔══════════════════════════════════════╗  ║  ║
║  ║  ║  ╔════════════════════════════════╗  ║  ║  ║
║  ║  ║  ║  ╔══════════════════════════╗  ║  ║  ║  ║
║  ║  ║  ║  ║  ╔════════════════════╗  ║  ║  ║  ║  ║
║  ║  ║  ║  ║  ║  ╔══════════════╗  ║  ║  ║  ║  ║  ║    ┓ 8 marbles representing a byte
║  ║  ║  ║  ║  ║  ║  ╔════════○  ○  ○  ○  ○  ○  ○  ○    ┛ This is the main variable
║  ║  ║  ║  ║  ║  ║  ║        ╚═╗╚═╗╚═╗╚═╗╚═╗╚═╗╚═╗╚═╗  ┓
║  ║  ║  ║  ║  ║  ║  ║        ╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝  ┃
║  ║  ║  ║  ║  ║  ║  ║     ○══╬╛═╬╛═╬╛═╬╛═╬╛═╬╛═╬╛═╬╛═╗ ┃ Synchronization
║  ║  ║  ║  ║  ║  ║  ║     ║  ╚═╗╚═╗╚═╗╚═╗╚═╗╚═╗╚═╗╚═╗║ ┃ Right-most marble exits first
║  ║  ║  ║  ║  ║  ║  ║     ║  ╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝║ ┃
║  ║  ║  ║  ║  ║  ║  ║     ╚══╬╛═╬╛═╬╛═╬╛═╬╛═╬╛═╬╛═╬╛═╝ ┛
║  ║  ║  ║  ║  ║  ║  ║        ╙○ ╙○ ╙○ ╙○ ╙○ ╙○ ╙○ ╙○   ┓ Set value to 0x21
║  ║  ║  ║  ║  ║  ║  ║        ║  ║  ┃  ║  ║  ║  ║  ┃    ┛ (the ascii character '!')
║  ║  ║  ║  ║  ║  ║  ║        ╟◆ ╟◆ ╟◆ ╟◆ ╟◆ ╟◆ ╟◆ ╟◆   ┓
║  ║  ║  ║  ║  ║  ║  ║        ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃    ┃ Write the byte to stdout
║  ║  ║  ║  ║  ║  ║  ║        ╟◇ ╟◇ ╟◇ ╟◇ ╟◇ ╟◇ ╟◇ ╟◇   ┃ LSB is on the right
║  ║  ║  ║  ║  ║  ║  ║        ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃    ┛
║  ║  ║  ║  ║  ║  ║  ║        ╚═╗╚═╗╚═╗╚═╗╚═╗╚═╗╚═╗╚═╗  ┓
║  ║  ║  ║  ║  ║  ║  ║        ╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝  ┃
║  ║  ║  ║  ║  ║  ║  ║     ○══╬╛═╬╛═╬╛═╬╛═╬╛═╬╛═╬╛═╬╛═╗ ┃ Synchronization
║  ║  ║  ║  ║  ║  ║  ║     ║  ╚═╗╚═╗╚═╗╚═╗╚═╗╚═╗╚═╗╚═╗║ ┃ Right-most marble exits first
║  ║  ║  ║  ║  ║  ║  ║     ║  ╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝╔╤╝║ ┃
║  ║  ║  ║  ║  ║  ║  ║     ╚══╬╛═╬╛═╬╛═╬╛═╬╛═╬╛═╬╛═╬╛═╝ ┛
║  ║  ║  ║  ║  ║  ║  ║        ╙○ ╙○ ╙○ ╙○ ╙○ ╙○ ╙○ ╙○   ┓ Read a byte from stdin
║  ║  ║  ║  ║  ║  ║  ║        ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃    ┃ LSB is on the right
║  ║  ║  ║  ║  ║  ║  ║        ╙◇ ╙◇ ╙◇ ╙◇ ╙◇ ╙◇ ╙◇ ╙◇   ┛
║  ║  ║  ║  ║  ║  ║  ║        ╟◆ ╟◆ ╟◆ ╟◆ ╟◆ ╟◆ ╟◆ ╟◆   ┓
║  ║  ║  ║  ║  ║  ║  ║        ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃    ┃ Write the byte to stdout
║  ║  ║  ║  ║  ║  ║  ║        ╟◇ ╟◇ ╟◇ ╟◇ ╟◇ ╟◇ ╟◇ ╟◇   ┃ LSB is on the right
║  ║  ║  ║  ║  ║  ║  ║        ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃    ┛
║  ║  ║  ║  ║  ║  ║  ╚════════╝  ║  ║  ║  ║  ║  ║  ║
║  ║  ║  ║  ║  ║  ╚══════════════╝  ║  ║  ║  ║  ║  ║
║  ║  ║  ║  ║  ╚════════════════════╝  ║  ║  ║  ║  ║
║  ║  ║  ║  ╚══════════════════════════╝  ║  ║  ║  ║
║  ║  ║  ╚════════════════════════════════╝  ║  ║  ║
║  ║  ╚══════════════════════════════════════╝  ║  ║
║  ╚════════════════════════════════════════════╝  ║
╚══════════════════════════════════════════════════╝

This is the first marbles submission ever :)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.