76
\$\begingroup\$

To "function nest" a string, you must:

  • Treat the first character as a function, and the following characters as the arguments to that function. For example, if the input string was Hello, then the first step would be:

    H(ello)
    
  • Then, repeat this same step for every substring. So we get:

    H(ello)
    H(e(llo))
    H(e(l(lo)))
    H(e(l(l(o))))
    

Your task is to write a program or function that "function nests" a string. For example, if the input string was Hello world!, then you should output:

H(e(l(l(o( (w(o(r(l(d(!)))))))))))

The input will only ever contain printable ASCII, and you may take the input and the output in any reasonable format. For example, STDIN/STDOUT, function arguments and return value, reading and writing to a file, etc.

For simplicity's sake, you may also assume the input will not contain parentheses, and will not be empty.

Input:
Nest a string
Output:
N(e(s(t( (a( (s(t(r(i(n(g))))))))))))

Input:
foobar
Output:
f(o(o(b(a(r)))))

Input:
1234567890
Output:
1(2(3(4(5(6(7(8(9(0)))))))))

Input:
code-golf
Output:
c(o(d(e(-(g(o(l(f))))))))

Input:
a
Output:
a

Input:
42
Output:
4(2)

As usual, all of our default rules and loopholes apply, and the shortest answer scored in bytes wins!

\$\endgroup\$
  • 21
    \$\begingroup\$ Ahem: Is this message anything to do with the challenge? :-) \$\endgroup\$ – wizzwizz4 Oct 18 '16 at 18:46
  • 11
    \$\begingroup\$ T​I​L 4​2​ ​= 8 \$\endgroup\$ – ETHproductions Oct 18 '16 at 21:48
  • \$\begingroup\$ What is maximum length for the input string? Incase of recursive methods \$\endgroup\$ – Ferrybig Oct 23 '16 at 20:30
  • \$\begingroup\$ Is the output the execution of said function, or merely the string itself? \$\endgroup\$ – nl-x Oct 24 '16 at 12:24
  • 1
    \$\begingroup\$ @kamoroso94 You may take the input and the output in any reasonable format. A list of characters seems perfectly reasonable to me. \$\endgroup\$ – DJMcMayhem Sep 1 '17 at 15:29

91 Answers 91

0
\$\begingroup\$

Racket 195 bytes

(let p((r "")(l(reverse(string->list s)))(i 0))(cond[(= i(length l))r][(= i 0)(set! r(string(list-ref l i)))
(p r l(+ 1 i))][(set! r(string-append(string(list-ref l i))"("r")" ))(p r l(+ 1 i))]))

Ungolfed:

(define (f s)
  (let loop ((r "")
             (l (reverse (string->list s)))
             (i 0))
    (cond
      [(>= i (length l)) r] 
      [(= i 0) (set! r (string (list-ref l i)))
               (loop r l (add1 i))]
      [else (set! r (string-append (string (list-ref l i)) "(" r ")" ))
            (loop r l (add1 i))]
      )))

Testing:

(f "Hello")

Output:

"H(e(l(l(o))))"

Edit: 2 bytes saved following suggestion by @JonathanFrech (add1 to + 1)

\$\endgroup\$
  • \$\begingroup\$ + 1 is shorter than add1. \$\endgroup\$ – Jonathan Frech Aug 28 '18 at 16:15
32
\$\begingroup\$

JavaScript (ES6), 40 34 33 bytes

Saved 6 bytes, thanks to ETHproductions

A recursive function.

f=([c,...s])=>s+s?c+`(${f(s)})`:c

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ Nice trick with 1/s. \$\endgroup\$ – ETHproductions Oct 18 '16 at 19:38
  • \$\begingroup\$ Super nice trick with ([c,...s]) you should write a tip \$\endgroup\$ – edc65 Oct 18 '16 at 21:27
  • \$\begingroup\$ @edc65 Just for sake of clarity, this one was suggested by ETHproductions. \$\endgroup\$ – Arnauld Oct 18 '16 at 21:40
  • \$\begingroup\$ o well, someone has to write a tip anyway \$\endgroup\$ – edc65 Oct 18 '16 at 21:42
  • 1
    \$\begingroup\$ @jmingov thank you, I know. The point here is using DA to to slice a string in a very short way (very shorter than .slice) \$\endgroup\$ – edc65 Oct 19 '16 at 7:16
1
\$\begingroup\$

C++, 66 bytes

[&](string s){return s[1]?s.substr(0,1)+"("+f(s.substr(1))+")":s;}

Try it Online

Matlab, 45 bytes

@(s)fold(@(x,y)strcat(y,'(',x,')'),fliplr(s))

Try it Online!

The problem with this is that octave in try it online doesn't really support the fold function which of course exists in Matlab. Let me know if I should delete this solution since we can't test it on tio.

\$\endgroup\$
  • 1
    \$\begingroup\$ Being able to test a submission on TIO is not a requirement, so your MATLAB answer is just fine. It's preferable to post different solutions in different answers though, so they can be voted on independently. \$\endgroup\$ – Dennis Aug 28 '18 at 14:18
1
\$\begingroup\$

Forth (gforth), 66 bytes

: f 1- 2dup 0 ?do dup 1 type ." ("') over c! 1+ loop 1 type type ;

Try it online!

Explanation

Prints each character of the string (except the last) followed by an open parenthesis, then overwrites the string and replaces the character with a close parenthesis. At the end, prints the last character, and then prints the string (now consisting of all close-parentheses).

Code Explanation

: f             \ start a new word definition
  1- 2dup       \ subtract one from the string length and duplicate the string identifier
  0 ?do         \ loop from 0 to string length - 2
    dup         \ duplicate the current string address
    1 type      \ output the character at the current address
    ." ("       \ output an open parenthesis
    ') over c!  \ get the char-code for a close-parenthesis, then write to the current address
    1+          \ add 1 to the current address
  loop          \ end the loop
  1 type type   \ output the last character, then output the string of parenthesis
;               \ end the word definition
\$\endgroup\$
1
\$\begingroup\$

J, 29 bytes

f=:(')'#~<:@#),~}.@,@('(',.])

Try it online!

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

Japt, 11 bytes

¬q'( +UÅî')

Try it

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

Whitespace, 132 bytes

[S S S N
_Push_0][N
S S N
_Create_Label_LOOP][S N
S _Duplicate][S N
S _Duplicate][T N
T   S _Read_characters_as_STDIN][T  T   T   _Retrieve][S S S T  S T S S T   N
_Push_41_)][T   S S T   _Subtract][N
T   S S N
_If_0_Jump_to_Label_PRINT_TRAILING][S N
S _Duplicate][N
T   S T N
_If_0_Jump_to_Label_SKIP][S S S T   S T S S S N
_Push_40_(][T   N
S S _Print_as_character][N
S S T   N
_Create_Label_SKIP][S N
S _Duplicate][T T   T   _Retrieve][T    N
S S _Print_as_character][S S S T    N
_Push_1][T  S S S _Add][N
S N
N
_Jump_to_Label_LOOP][N
S S S N
_Create_Label_PRINT_TRAILING][S S S T   N
_Push_1][T  S S T   _Subtract][S N
S _Duplicate][N
T   S S S N
_If_0_Jump_to_Label_EXIT][S S S T   S T S S T   N
_Push_41_)][T   N
S S _Print_as_character][N
S N
S N
_Jump_to_Label_PRINT_TRAILING]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Try it online (with raw spaces, tabs and new-lines only).

Since Whitespace's STDIN don't know when the input is done since it can only read a single character or number at a time, the input will need a trailing ) to indicate we're done inputting (which is possible since the challenge rules state: "For simplicity's sake, you may also assume the input will not contain parentheses").

Explanation in pseudo-code:

Integer n = 0
Start LOOP:
  Character c = read character from STDIN
  If(c == ')'):
    Jump to function PRINT_TRAILING
  If(n != 0)
    Print '(' to STDOUT
  Print c to STDOUT
  n = n + 1
  Jump to next iteration of LOOP

function PRINT_TRAILING:
  n = n - 1
  If(n == 0)
    Stop program
  Print ')' to STDOUT
  Jump to function PRINT_TRAILING
\$\endgroup\$
0
\$\begingroup\$

Gol><>, 37 bytes

14a*iov
!vo$P$>:oi:P?
:>~~:?!;9sso1-:

Try it online!

Reads from stdin, outputs to stdout

Explanation:

14a*            Pushes 1 (num of characters so far) and 40 (ASCII for open paren) onto stack
    io          Reads a character and outputs it
      v         Drops to next line of golfed code

      >         Directs pointer to the right
       :o       Duplicates and outputs the (
         i      Inputs a character
!v        :P?   Drops to next line of golfed code if no more chars
  o             Outputs character
   $P$          Increments the character counter

 >              Directs pointer to the right
  ~~            Discard unneeded stack values
    :?!;        Exits if counter == 0
        9sso    Outputs closing paren
            1-  Decrement counter
:             : Duplicate counter twice (so that it isn't discarded by the '~'
\$\endgroup\$
  • \$\begingroup\$ ioiEH')('o$! \$\endgroup\$ – Jo King Aug 28 '18 at 8:17
  • \$\begingroup\$ @JoKing well now I feel inadequate /s \$\endgroup\$ – xornob Aug 28 '18 at 8:24
  • \$\begingroup\$ Well, when creating a Gol><> answer you need to check if there's an existing ><> answer you can adapt ;) \$\endgroup\$ – Jo King Aug 28 '18 at 8:26
  • \$\begingroup\$ Welcome to PPCG! looks like you have too many parentheses: there should be no opening parenthese after the last letter of the string. \$\endgroup\$ – JayCe Aug 28 '18 at 13:34
1
\$\begingroup\$

Kotlin, 83 63 bytes

-20 bytes using toList; thanks to 12Me21 tipping me off this could be shorter.

{s:String->s.toList().joinToString("(")+")".repeat(s.length-1)}

Try it online!

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

Stax, 8 6 bytes

-2 thanks to @recursive!

çΔ \Γ]

Run and debug it at staxlang.xyz!

Unpacked (7 bytes) and explanation:

Mrks:{+
M          Transpose array. This turns a string into an array of length-1 strings.
 r         Reverse string.
  k        Fold array using the rest of the program as a block:
   s         Swap. This puts the accumulator on top of the current element.
    :{       Wrap in parentheses.
      +      Concatenate.
           Implicit print at end of program!
\$\endgroup\$
  • \$\begingroup\$ If you transpose the input string, you can get rid of the stringifications, and pack down to 6. Mrks:{+ \$\endgroup\$ – recursive May 24 '18 at 17:03
  • \$\begingroup\$ @recursive Ah. That's what I was looking for. Definitely beats {]m for the same functionality! \$\endgroup\$ – Khuldraeseth na'Barya May 25 '18 at 19:57
0
\$\begingroup\$

Python 3.6+, 39 bytes

z=lambda x,*y:x+f'({z(*y)})'if y else x

Takes each character as an individual argument (can be used like z(*'asdf')). This uses recursion with iterable unpacking and f-string interpolation.


Note: This is almost non-competing. Python 3.6 was released after this challenge was posted, but was feature-frozen in beta on 2016-09-12, so this feature was available before the challenge was posted.


Though it turns out you can do it in the same number of bytes with %-interpolation (this works on more Python versions):

z=lambda x,*y:x+'(%s)'%z(*y)if y else x
\$\endgroup\$
0
\$\begingroup\$

Canvas, 8 bytes

(*;L╷)×+

Try it here!

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

SNOBOL4 (CSNOBOL4), 111 bytes

	INPUT LEN(1) . O REM . N
	W =SIZE(N)
N	N LEN(1) . X REM . N	:F(O)
	O =O '(' X	:(N)
O	OUTPUT =O DUPL(')',W)
END

Try it online!

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

R, 56 bytes

function(s)c(paste(s,collapse="("),rep(")",length(s)-1))

Try it online!

Plain old R. Recursive solution below. Both input and output are vectors of characters.

R, 57 bytes

f=function(s)"if"(length(s)>1,c(s[1],"(",f(s[-1]),")"),s)

Try it online!

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

Java 10, 71 bytes

s->{var r="";for(int i=s.length;i-->1;r="("+s[i]+r+")");return s[0]+r;}

Shorter than the existing two recursive Java answers.

Input as String-array of each character.

Try it online.

s->{               // Method with String-array parameter and String return-type
  var r="";        //  Result-String, starting empty
  for(int i=s.length;i-->1; 
                   //  Loop backwards over the array, skipping the first character
    r=             //   Set the result to:
      "("          //    An opening parenthesis,
      +s[i]        //    appended with the current character,
      +r           //    appended with the current result-String,
      +")");       //    appended with a closing parenthesis
  return s[0]+r;}  //  Return the first character, appended with the result-String
\$\endgroup\$
0
\$\begingroup\$

Japt, 11 bytes

ç q') iUq'(

Try it online!

Takes an array of 1-length strings as input.

How it works

Uç q') iUq'(

Uç    Replace input array's every element with `undefined`
q')   Join with ")"
i     Insert to the beginning of above result...
Uq'(    Input array joined with "("

Uses a JS trick: undefined elements of an Array is converted to empty strings on join.

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

Implicit, 24 23 bytes

~@~.(0-1@40@~.);;(0@41;

Try it online!

Ungolfed/explained:

~@~.     # read first character, print, read second, increment
(0       # do-while top of stack truthy
 -1      #  decrement top of stack
 @40     #  print open parenthesis (ASCII 40)
 @       #  print top of stack
 ~.      #  read char and increment
)        # while top of stack truthy
;;       # pop top two values (EOF, last char)

(0       # do-while top of stack truthy
 @41     #  print close parenthesis (ASCII 41)
 ;       #  pop top of stack
¶        # (implicit) forever

Test cases:

Nest a string
N(e(s(t( (a( (s(t(r(i(n(g))))))))))))

foobar
f(o(o(b(a(r)))))

1234567890
1(2(3(4(5(6(7(8(9(0)))))))))

code-golf
c(o(d(e(-(g(o(l(f))))))))

a
a

42
4(2)
\$\endgroup\$
2
\$\begingroup\$

QBIC, 64 bytes

Way too large. Posted as an incentive to get my butt moving again on the QBIC project.

;_LA|[a-1|Z=Z+$mid$|(A,b,1)+@(|]Z=Z+$right$|(A,1)[a-1|Z=Z+@)|]?Z

All those $mid$| and $right$|s should be turned into QBIC commands, but to do that I first need to solve a problem with nesting function calls...


EDIT: Got my butt moving. Now in 48 bytes:

_L;|[a-1|Z=Z+_sA,b,1|+@(`]Z=Z+_sA,-1|[a-1|Z=Z+@)
\$\endgroup\$
  • \$\begingroup\$ Huh. QBIC looks interesting. Is there a github project I could follow? Or a README describing what it is? \$\endgroup\$ – DJMcMayhem Nov 28 '16 at 18:11
  • \$\begingroup\$ @DrMcMoylex I swear, the day I figure out how Github works ... The project lives in a shared folder on a Google Drive, link in the header. Some info o getting started here and here. \$\endgroup\$ – steenbergh Nov 28 '16 at 18:23
  • \$\begingroup\$ Why is QBIC not on TIO? \$\endgroup\$ – MD XF Nov 10 '17 at 18:36
  • \$\begingroup\$ @MDXF Well, QBIC code is converted into QBasic code, which is run in Dosbox. I do not believe that such an environment can be easily set up for use on the web... I am taking suggestions however :) \$\endgroup\$ – steenbergh Nov 10 '17 at 20:19
  • \$\begingroup\$ @steenbergh Ah, that's true. I'm actually looking into ways to get QBasic / ABASIC / Applesoft Basic onto TIO. Right now it's looking like I'm going to need to write my own interpreters. >.< \$\endgroup\$ – MD XF Nov 11 '17 at 4:55
1
\$\begingroup\$

Java 8 (63 82 bytes)

"s" is a char[]

s->{String r="",p=r;for(char c:s){r+="("+c;p+=")";}return r+p;}

s->{String r="",p=r;for(char c:s){if(r==p)r+=c;else{r+="("+c;p+=")";}}return r+p;}

Edit: I didn't realise there aren't parentheses around the whole string.

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

Ly, 50 bytes

iyspr1[1[=!["("o1$]p1$]1[=[pp2$]p1$]o]l1-[")"o1-];

Try it online!

This is ridiculous. Ly is lacking severely in the string manipulation department.

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

Swift 3.1,  85  83 bytes

This is an anonymous function accepting an Array of Strings and returning a String.

{$0.joined(separator:"(")+String(repeating:")",count:$0.count-1)}as([String])->String

Try it here!

Swift 3.1,  88 87  86 bytes

This is a named function accepting an Array of Strings and printing a String.

func f(n:[String]){print(n.joined(separator:"(")+(1..<n.count).map{_ in")"}.joined())}

Try it here!

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

tcl, 66

puts [join [split $s ""] (][string repe ) [expr [string le $s]-1]]

Testable on http://rextester.com/live/SAXFO71660

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

Groovy, 46 bytes

{it.reverse().inject{r,i->")$r($i"}.reverse()}
\$\endgroup\$
1
\$\begingroup\$

Haskell, 38 30 bytes

8 bytes saved thanks to @JanDvorak

f[x]=[x]
f(x:s)=x:'(':f s++")"

This is my first attempt at a haskell golf, probably not optimal yet.

Explanation

We define a function f. If this function receives input that matches the pattern [x], that is a length 1 string, we return the input. If we receive anything else as input we return the x:'(':f s++")", or the first character plus the rest result of f on the rest of the string all enclosed in parentheses.

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

PHP, 51 60 68 63 bytes

Why not just do what´s asked for instead of emulating it? Recurse!

function n($s){return$s[1]>""?"$s[0](".n(substr($s,1)).")":$s;}
\$\endgroup\$
  • \$\begingroup\$ why not change $s[1]>"" into just $s[1]? 3 chars less. \$\endgroup\$ – nl-x Oct 24 '16 at 13:40
  • \$\begingroup\$ @nl-x because the 0 character evaluates to false \$\endgroup\$ – Titus Oct 24 '16 at 13:43
  • \$\begingroup\$ @nl-x ... but I learned something just as long in the meantime. \$\endgroup\$ – Titus Mar 7 '17 at 23:53
  • \$\begingroup\$ Please do explain what you did there... \$\endgroup\$ – nl-x Mar 8 '17 at 7:26
  • \$\begingroup\$ @nl-x I messed it up. I intended a shorter check on the second character using bitwise arithmetics, but checked the string for emptiness instead. Rolled back. \$\endgroup\$ – Titus Mar 8 '17 at 13:02
0
\$\begingroup\$

ForceLang, 132 bytes

def S set
S a io.readln()
S i 0
S b ")"
label 1
io.write a.charAt i
S i i+1
if i+-a.len
 io.write "("
 goto 1
io.write b.repeat i+-1
\$\endgroup\$
3
\$\begingroup\$

Brain-Flak, 118 84 + 1 = 85 bytes

Try it online

([[]]<{({}<>)((((()()()()()){}){}){})<>}>()){({}()<(<>({})<>())>)}{}<>{}{({}<>)<>}<>

This requires the -fc flag to run giving it an extra byte. -f flag is standard for passing input.


Explanation

([[]]<        #Store a copy of the stack height before hand in the scope
 {            #While there is something on the stack...
  ({}<>)      #Move something over and...
  ((((()()()()()){}){}){}) #Put a paren on top
  <>          #Swap back
}
>())          #Put the 1-stack height down
{             #While that is not zero
 ({}()<       #Add one and
  (<>({})<>())#Silently move a copy of the top of the other stack over (close paren)
 >)
}{}
<>{}          #Remove extra open paren
{({}<>)<>}<>  #Combine the two stacks
\$\endgroup\$
2
\$\begingroup\$

Mathematica, 35 27 bytes bytes

Saved 8 bytes on adding the appropriate number of ")" to the end thanks to alephalpha

#~Riffle~"("<>Most[0#+")"]&

Input is a list of characters. Riffles "(" between each character, then adds that many ")" minus 1 to the end. Specifically, multiplies the input by 0, adds ")" and then takes Most of the list.

e.g.

#~Riffle~"("<>Most[0#+")"]&[{"H","e","l","l","o"}]

{"H","e","l","l","o"}~Riffle~"("<>Most[0{"H","e","l","l","o"}+")"]

{"H","(","e","(","l","(","l","(","o"}<>Most[{0,0,0,0,0}+")"]

{"H","(","e","(","l","(","l","(","o"}<>Most[{")",")",")",")",")"}]

{"H","(","e","(","l","(","l","(","o"}<>{")",")",")",")"}

"H(e(l(l(o))))"
\$\endgroup\$
  • 1
    \$\begingroup\$ #~Riffle~"("<>Most[0#+")"]& \$\endgroup\$ – alephalpha Jan 11 '17 at 14:30
1
\$\begingroup\$

Python 3, 43 bytes

lambda x:print(*x,sep='(',end=')'*~-len(x))

Longer than shortest Python submission, but it is fairly different, so I thought I should post it. It is a function, but prints to STDOUT.

\$\endgroup\$
  • \$\begingroup\$ This prints one extra close paren each time. Try ~-len(x) rather than len(x) \$\endgroup\$ – Sriotchilism O'Zaic Jan 11 '17 at 2:16
  • \$\begingroup\$ @WheatWizard Thank you, I don't know how I missed that. \$\endgroup\$ – nedla2004 Jan 11 '17 at 12:49
1
\$\begingroup\$

Clojure, 94 60 59 48 bytes

-34 by making it a actual recursive solution. The biggest saving here was getting rid of the repeat part to generate the end brackets.

-1 by rearranging it, eliminating a conditional.

-11 bytes thanks to NikoNyrh. Now deconstructs the parameter directly.

(defn n[[f & r]](if(str f(if r(str\((n r)\))))))

Recursive. Basically (str head "(" (recur tail) ")"), with the brackets being added only if a tail exists.

Uses unoptimized recursion. Can handle strings up to around 5235 characters long.

Ungolfed:

(defn nest [[f & r]]
    (if f ; When it exists, construct string and recur, else, base-case
      (str f (if r (str \( (nest r) \))))))
\$\endgroup\$
  • \$\begingroup\$ I guess you could merge function definition and let to (defn n[[f & r]](if f(str f(if r(str\((n r)\))))) :) \$\endgroup\$ – NikoNyrh Jan 11 '17 at 0:38
  • \$\begingroup\$ @NikoNyrh You're right! I hate deconstructing in the parameter list in real code, but that certainly helps here. Thanks! \$\endgroup\$ – Carcigenicate Jan 11 '17 at 0:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.