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\$
  • 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 Apr 30 '18 at 23:04
  • 2
    \$\begingroup\$ Do we have to support leading 0s? They fit the regex. \$\endgroup\$ – Jo King May 1 '18 at 2:04
  • 2
    \$\begingroup\$ Possible duplicate of Sugar Free Syntax \$\endgroup\$ – NoOneIsHere May 1 '18 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 May 1 '18 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 May 1 '18 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
    \$\begingroup\$ +1, I love the +0 trick! \$\endgroup\$ – B. Mehta May 1 '18 at 22:08
5
\$\begingroup\$

Python 2, 50 bytes

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

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ So beautiful ;-; \$\endgroup\$ – Neil May 1 '18 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\$
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\$
  • \$\begingroup\$ @ovs 24? \$\endgroup\$ – ASCII-only Apr 30 '18 at 23:21
  • \$\begingroup\$ also 24? \$\endgroup\$ – ASCII-only Apr 30 '18 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 May 1 '18 at 0:42
  • \$\begingroup\$ Oh, that's right. I forgot \b was a thing for some reason >_> 20 bytes @Mnemonic \$\endgroup\$ – ASCII-only May 1 '18 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\$
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\$
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\$
  • 1
    \$\begingroup\$ 71 bytes with a single substitution based on my Ruby answer. \$\endgroup\$ – Kirill L. Mar 3 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 Mar 3 at 15:27
  • \$\begingroup\$ -2 more, I totally forgot about a shorter \K lookbehind \$\endgroup\$ – Kirill L. Mar 3 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\$
  • \$\begingroup\$ substr is shorter and the first paste0 can be paste to get this to 136 bytes. \$\endgroup\$ – Giuseppe May 3 '18 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 May 3 '18 at 16:14
  • \$\begingroup\$ @Giuseppe Thanks for the -4 bytes! I wish we had something shorter. Recursive solution maybe? \$\endgroup\$ – JayCe May 3 '18 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\$
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\$

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.