17
\$\begingroup\$

In Elixir, (linked) lists are in the format [head | tail] where head can be anything and tail is a list of the rest of the list, and [] - the empty list - is the only exception to this.

Lists can also be written like [1, 2, 3] which is equivalent to [1 | [2 | [3 | []]]]

Your task is to convert a list as described. The input will always be a valid list (in Elixir) containing only numbers matching the regex \[(\d+(, ?\d+)*)?\]. You may take the input with (one space after each comma) or without spaces. The output may be with (one space before and after each |) or without spaces.

For inputs with leading zeroes you may output either without the zeroes or with.

Input must be taken as a string (if writing a function), as does output.

Examples

[] -> []
[5] -> [5 | []]
[1, 7] -> [1 | [7 | []]]
[4, 4, 4] -> [4 | [4 | [4 | []]]]
[10, 333] -> [10 | [333 | []]]

related, not a duplicate as this in part involves adding mode ] to the end. Additionally, the Haskell answer here is quite different to the one there.

\$\endgroup\$
9
  • 5
    \$\begingroup\$ -1 from me. Cumbersome IO formats are discouraged. If the input is a list, let us take it as a list instead of having 90% of our code just parsing the input \$\endgroup\$
    – Jo King
    Commented Apr 30, 2018 at 23:04
  • 2
    \$\begingroup\$ Do we have to support leading 0s? They fit the regex. \$\endgroup\$
    – Jo King
    Commented May 1, 2018 at 2:04
  • 2
    \$\begingroup\$ Possible duplicate of Sugar Free Syntax \$\endgroup\$ Commented May 1, 2018 at 2:35
  • 5
    \$\begingroup\$ @JoKing I'd argue that here the challenge itself is about converting between two specific formats, so parsing the input is a fundamental part of the challenge and not something extra added to it. P.S. I've realized only now what your nickname really is xD \$\endgroup\$
    – Leo
    Commented May 1, 2018 at 4:43
  • 2
    \$\begingroup\$ @MuhammadSalman: the challenge is tagged as "parsing", so converting from/to a string is a substantial part of it with intent. \$\endgroup\$
    – nimi
    Commented May 1, 2018 at 9:52

26 Answers 26

9
\$\begingroup\$

Haskell, 50 bytes

f.read
f(a:b)='[':show(a+0)++'|':f b++"]"
f _="[]"

Try it online!

The +0 lets the Haskell type checker know that we are dealing with lists of numbers, so read will parse the input string for us.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ +1, I love the +0 trick! \$\endgroup\$
    – B. Mehta
    Commented May 1, 2018 at 22:08
6
\$\begingroup\$

Python 2, 50 bytes

r='%s'
for x in input():r%='[%s|%%s]'%x
print r%[]

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ So beautiful ;-; \$\endgroup\$
    – Neil
    Commented May 1, 2018 at 19:06
4
\$\begingroup\$

JavaScript (ES6), 50 bytes

s=>eval(s).map(v=>`[${p+=']',v}|`,p='[]').join``+p

Try it online!


Recursive version, 51 bytes

f=(s,[v,...a]=eval(s))=>1/v?`[${v}|${f(s,a)}]`:'[]'

Try it online!

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

Retina, 39 33 32 20 bytes

\b]
,]
+`,(.*)
|[$1]

Saved 13 bytes thanks to H.PWiz, ovs, ASCII-only, and Neil.
Try it online!

Explanation

\b]
,]

If we don't have an empty list, add a trailing comma.

+`,(.*)
|[$1]

While there are commas, wrap things with |[ thing ].

\$\endgroup\$
4
  • \$\begingroup\$ @ovs 24? \$\endgroup\$
    – ASCII-only
    Commented Apr 30, 2018 at 23:21
  • \$\begingroup\$ also 24? \$\endgroup\$
    – ASCII-only
    Commented Apr 30, 2018 at 23:27
  • \$\begingroup\$ @ASCII-only You can save another 4 bytes by replacing \b] with ,]. (Otherwise I had independently discovered the same solution.) \$\endgroup\$
    – Neil
    Commented May 1, 2018 at 0:42
  • \$\begingroup\$ Oh, that's right. I forgot \b was a thing for some reason >_> 20 bytes @Mnemonic \$\endgroup\$
    – ASCII-only
    Commented May 1, 2018 at 1:18
4
\$\begingroup\$

Perl 5 -pl, 31 28 bytes

s/\d\K]/,]/;$\=']'x s/,/|[/g

Try it online!

How?

-p                    # (command line) Implicit input/output via $_ and $\
s/\d\K]/,]/;          # insert a comma at the end if the list is not empty
$\=']'x s/,/|[/g      # At the end of the run, output as many ']' as there are
                      # commas in the input.  Replace the commas with "|["
\$\endgroup\$
3
\$\begingroup\$

Elixir, 111 85 bytes

f=fn[h|t],f->"[#{h}|#{f.(t,f)}]"
[],_->"[]"
h,f->f.(elem(Code.eval_string(h),0),f)end

Try it online!

I have never used Elixir before. Defines a function that takes a string and a reference to itself and returns a string.

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

Ceylon, 113 bytes

String p(String s)=>s.split(" ,[]".contains).select((x)=>!x.empty).reversed.fold("[]")((t,h)=>"[``h`` | ``t``]");

Try it online!

Here is it written out:

// define a function p mapping Strings to Strings.
String p(String s) =>
    // we split the string at all characters which are brackets, comma or space.
    s.split(" ,[]".contains)    // → {String+}, e.g.  { "", "1", "7", "" }
    // That iterable contains empty strings, so let's remove them.
    // Using `select` instead of `filter` makes the result a sequential instead of
    // an Iterable.
     .select((x)=>!x.empty)    // → [String*], e.g.   [1, 7]
    // now invert the order.
    // (This needs a Sequential (or at least a List) instead of an Iterable.)
     .reversed                 // → [String*], e.g.   [7, 1]
    // Now iterate over the list, starting with "[]", and apply a function
    // to each element with the intermediate result.
     .fold("[]")                       // → String(String(String, String))
    //    This function takes the intermediate result `t` (for tail) and an element
    //    `h` (for head), and puts them together into brackets, with a " | " in the
    //    middle. This uses String interpolation, I could have used `"+` and `+"`
    //    instead for the same length.
          ((t,h)=>"[``h`` | ``t``]");  // → String

Try it online!

As noted by ovs in a (now deleted) comment: If one select the "without spaces" options for input and output indicated in the question, one can safe 3 more bytes (the obvious ones with spaces in them).

If we don't need to parse the input, but just could get a sequence as input, it gets much shorter (69 bytes).

String p(Object[]s)=>s.reversed.fold("[]")((t,h)=>"[``h`` | ``t``]");

Try it online!

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

Python 3, 65 bytes

lambda k:"["+''.join(f"{u}|["for u in eval(k))+-~len(eval(k))*"]"

Try it online!

If the input could be a list instead, then:

Python 3, 53 bytes

lambda k:"["+''.join(f"{u}|["for u in k)+-~len(k)*"]"

Try it online!

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

SNOBOL4 (CSNOBOL4), 114 bytes

	I =INPUT
S	N =N + 1	
	I SPAN(1234567890) . L REM . I	:F(O)
	O =O '[' L ' | '	:(S)
O	OUTPUT =O '[' DUPL(']',N)
END

Try it online!

	I =INPUT				;* read input
S	N =N + 1				;* counter for number of elements (including empty list)
	I SPAN(1234567890) . L REM . I	:F(O)	;* get value matching \d until none left
	O =O '[' L ' | '	:(S)		;* build output string
O	OUTPUT =O '[' DUPL(']',N)		;* print O concatenated with a '[' and N copies of ']'
END
\$\endgroup\$
2
\$\begingroup\$

Stax, 19 bytes

É▲²:WlÖ└%ï╪☺╒▓"We↨Φ

Run and debug it

My first Stax post, so probably not optimal.

Unpacked and commented:

U,                      Put -1 under input
  {                     Block
   i                      Push loop index, needed later
    '[a$'|++              Wrap the element in "[...|"
            m           Map
             '[+        Add another "["
                s2+     Get the latest loop index + 2
                   ']*+ Add that many "]"

Run and debug this one

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

Husk, 22 bytes

+:'[J"|[":msr¹₁*₁Lr
"]

Try it online!

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

Befunge-98 (PyFunge), 22 21 bytes

'[,1;@j,]';#$&." |",,

Try it online!

If there weren't weird restrictions on output, we could do this in 18:

'[,1;@j,]';#$&.'|,

Fun fact, this is technically a program that does nothing in Python.

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

Ruby -p, 39 bytes

Full program:

$_[$&]="|[#$2]"while/(,|\d\K(?=]))(.*)/

Try it online!

Ruby, 48 45 bytes

Recursive function:

f=->s{(s[/,|\d\K(?=])/]&&="|[")&&f[s+=?]]||s}

Try it online!

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

R, 84 71 69 bytes

function(x){while(x<(x=sub('(,|\\d\\K(?=]))(.+)','|[\\2]',x,,T)))1;x}

Try it online!

  • -15 bytes thanks to @KirillL.
\$\endgroup\$
3
  • 1
    \$\begingroup\$ 71 bytes with a single substitution based on my Ruby answer. \$\endgroup\$
    – Kirill L.
    Commented Mar 3, 2019 at 15:19
  • \$\begingroup\$ @KirillL. : thanks, I was sure there was a shorter regex to do that, but I always mess up with lookarounds :D \$\endgroup\$
    – digEmAll
    Commented Mar 3, 2019 at 15:27
  • \$\begingroup\$ -2 more, I totally forgot about a shorter \K lookbehind \$\endgroup\$
    – Kirill L.
    Commented Mar 3, 2019 at 17:26
1
\$\begingroup\$

Proton, 57 bytes

k=>"["+''.join(str(u)+"|["for u:(e=eval(k)))+-~len(e)*"]"

Try it online!

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

Jelly, 19 bytes

ŒV©;€⁾|[”[;µ®L‘”]ẋṭ

Try it online!

A non-recursive alternative to Erik's solution.

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

Jelly, 18 bytes

ŒVḢ,ŒṘÇ”|;ƲƊ¹¡⁾[]j

Try it online!

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

Jelly, 18 bytes

ŒVµ⁾[]jj⁾|[ṫ3;”]ṁ$

A full program printing the result (as a monadic link it accepts a list of characters but returns a list of characters and integers).

Try it online!

How?

ŒVµ⁾[]jj⁾|[ṫ3;”]ṁ$ - Main link: list of characters  e.g. "[10,333]"
ŒV                 - evaluate as Python code              [10,333]
  µ                - start a new monadic chain, call that X
   ⁾[]             - list of characters                   ['[',']']
      j            - join with X                          ['[',10,333,']']
        ⁾|[        - list of characters                   ['|','[']
       j           - join                                 ['[','|','[',10,'|','[',333,'|','[',']']
           ṫ3      - tail from index three                ['[',10,'|','[',333,'|','[',']']
                 $ - last two links as a monad (f(X)):
              ”]   -   character                          ']'
                ṁ  -   mould like X                       [']',']'] (here 2 because X is 2 long)
             ;     - concatenate                          ['[',10,'|','[',333,'|','[',']',']',']']
                   - implicit (and smashing) print        [10|[333|[]]]
\$\endgroup\$
1
\$\begingroup\$

Java 10, 107 bytes

s->{var r="[]";for(var i:s.replaceAll("[\\[\\]]","").split(","))r="["+i+"|"+r+"]";return s.length()<3?s:r;}

Try it online.

Explanation:

s->{                       // Method with String as both parameter and return-type
  var r="[]";              //  Result-String, starting at "[]"
  for(var i:s.replaceAll("[\\[\\]]","") 
                           //  Removing trailing "[" and leading "]"
             .split(","))  //  Loop over the items
    r="["+i+"|"+r+"]";     //   Create the result-String `r`
  return s.length()<3?     //  If the input was "[]"
          s                //   Return the input as result
         :                 //  Else:
          r;}              //   Return `r` as result
\$\endgroup\$
1
\$\begingroup\$

Standard ML, 71 bytes

fun p[_]="]|[]]"|p(#","::r)="|["^p r^"]"|p(d::r)=str d^p r;p o explode;

Try it online! Uses the format without spaces. E.g. it "[10,333,4]" yields "[10|[333|[4]|[]]]]".

ungolfed

fun p [_]       = "]|[]]"          (* if there is only one char left we are at the end *)
  | p (#","::r) = "|[" ^ p r ^ "]" (* a ',' in the input is replaced by "|[" and an closing "]" is added to the end *)
  | p (d::r)    = str d ^ p r      (* all other chars (the digits and the initial '[') are converted to a string and concatenated to recursive result *)

val f = p o explode  (* convert string into list of chars and apply function p *)

Try it online!

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

R, 140 136 bytes

Down 4 bytes as per Giuseppe's sound advice.

function(l,x=unlist(strsplit(substr(l,2,nchar(l)-1),", ")))paste(c("[",paste0(c(x,"]"),collapse=" | ["),rep("]",length(x))),collapse="")

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ substr is shorter and the first paste0 can be paste to get this to 136 bytes. \$\endgroup\$
    – Giuseppe
    Commented May 3, 2018 at 16:07
  • 1
    \$\begingroup\$ Using eval, parse, and sub instead of unlist, strsplit and substr, I also only managed 136 bytes (I thought it might be shorter but it wasn't) \$\endgroup\$
    – Giuseppe
    Commented May 3, 2018 at 16:14
  • \$\begingroup\$ @Giuseppe Thanks for the -4 bytes! I wish we had something shorter. Recursive solution maybe? \$\endgroup\$
    – JayCe
    Commented May 3, 2018 at 16:55
1
\$\begingroup\$

R, 108 bytes

function(l)Reduce(function(x,y)paste0("[",x,"|",y,"]"),eval(parse(t=sub("]",")",sub("\\[","c(",l)))),"[]",T)

Try it online!

It took almost a year to find a better R solution than previous...should have known Reduce would be the answer! Outputs without spaces, input can be with or without spaces.

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

Python 2, 63 bytes

lambda s:'['+'|['.join(map(str,eval(s))+[']'])+']'*len(eval(s))

Try it online!

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

sed + -E, 46 bytes

:
s/\[([0-9]+)(, ?([^]]*)|())\]/[\1 | [\3]]/
t

A fairly straightforward approach. The second line takes [\d+, ...] and changes it to [\d | [...]]. The third line jumps back to the first line, if the substitution was successful. The substitution repeats until it fails and then the program terminates. Run with sed -E -f filename.sed, passing input via stdin.

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

Red, 110 bytes

func[s][if s ="[]"[return s]replace append/dup replace/all b: copy s",""|[""]"(length? b)- length? s"]""|[]]"]

Try it online!

Explanation of the ungolfed version:

f: func[s][                      
    if s = "[]" [return s]                    ; if the list is empty, return it    
    b: copy s                                 ; save a copy of the input in b 
    replace/all b "," "|["                    ; replace every "," with "|["  
    append/dup b "]" (length? b) - length? s  ; append as many "]" as there were ","
    replace b "]" "|[]]"                      ; replace the first "]" with "|[]]"     
]                                             ; the last value is returned implicitly

Red is so easily readable, that I doubt I needed adding the above comments :)

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

Perl 6, 38 bytes

{'['~S:g/\s|.<($/\|\[/~']'x$_+1}o&EVAL

Try it online!

\$\endgroup\$

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