11
\$\begingroup\$

Given a non-empty string containing only printable ASCII (codepoints 0x20 to 0x7E), write the shortest program or function that map the key to its value. Inside the string the key will always have a value and vice-versa.

How the key is made:

  • Start with an opening parenthesis (
  • Contains letters and/or numbers [a-zA-Z0-9]
  • It ends with a closing parenthesis )

What value does it refer to:

  • All characters until the next opening parenthesis or end of string
  • Contains letters and/or numbers [a-zA-Z0-9]

Context

This test is based on a real case study, i.e. the reading of the application identifiers following the GS1 standards. If you want more information you can look through the documentation at https://ref.gs1.org/ai/

Test Cases

input output
(01)99012345670019(10)Ab1234 01 -> 99012345670019 10 -> Ab1234
(3102)00122515190521 3102 -> 00122515190521
(337n)001234 337n -> 001234
\$\endgroup\$
9
  • 1
    \$\begingroup\$ @macOSisthebestOS Actually, in my explanation that case is not very clear. Technically I wrote that the value ​​can contain any character, therefore also parentheses. To clarify, since I didn't include your observation in the examples I modified the question by excluding special characters within the value. Being relatively new to the community I hope this action can follow the community guidelines. \$\endgroup\$ Commented Mar 27 at 13:48
  • 2
    \$\begingroup\$ I'm unclear as to what you mean by map the key to its value. For instance, I want to use a language whose only data type is string and doesn't have functions, only full programs, so should my program output a full program which performs the desired mapping? \$\endgroup\$
    – Neil
    Commented Mar 27 at 16:07
  • 1
    \$\begingroup\$ @Nail By "map" I mean connecting two elements as if they were key-value. You can write an output string that represents a json, an array, or whatever you prefer. The constant is that there is an association between the key and its value. \$\endgroup\$ Commented Mar 27 at 16:14
  • 1
    \$\begingroup\$ Is it guaranteed that the input will contain only keys and values? Several existing answers fail if additional junk (i.e. printable characters not in [a-zA-Z0-9]) is allowed to appear before/between/after the key-value pairs, e.g. ***(key1)value1***(key2)value2***. (I note that you state that 'the key will always have a value and vice-versa', but as I read it, this doesn't exclude additional junk.) \$\endgroup\$
    – Dingus
    Commented Mar 27 at 21:56
  • 5
    \$\begingroup\$ "You can write an output string that represents a json, an array, or whatever you prefer." My problem with this vague challenge is that I don't see how "whatever you prefer" excludes the format the input is already in. If [[01, 99012345670019], [10, Ab1234]] and {"01": "99012345670019", "10": "Ab1234"} and 01 -> 99012345670019 10 -> Ab1234 are all valid output formats, then why not (01)99012345670019(10)Ab1234? \$\endgroup\$
    – lynn
    Commented Mar 29 at 16:06

22 Answers 22

9
\$\begingroup\$

Python 3, 52 bytes

lambda x:dict(i.split(')')for i in x[1:].split('('))

Try it online!

\$\endgroup\$
8
\$\begingroup\$

Vyxal, 64 46 bitsv2, 8 5.75 bytes

\(/Ḣ\)/

Try it Online!

Bitstring:

0110100010010100000101101101001111001010010100

Returns a list of lists. -2.25 bytes thanks to @pacman256

Explained

\(/Ḣ\)/­⁡​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏⁠‎⁡⁠⁣‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁤‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏‏​⁡⁠⁡‌­
\(/      # ‎⁡Split the input on (s
   Ḣ     # ‎⁢Remove the first item
    \)/  # ‎⁣Split each item in that on )s
💎

Created with the help of Luminespire.

\$\endgroup\$
2
  • \$\begingroup\$ 5.75 \$\endgroup\$
    – pacman256
    Commented Mar 27 at 22:09
  • 7
    \$\begingroup\$ Oh, a very aesthetically pleasing solution! \$\endgroup\$
    – DLosc
    Commented Mar 28 at 2:51
8
\$\begingroup\$

Ruby, 42 31 25 bytes

->s{Hash[*s.scan(/\w+/)]}

Try it online!

Thanks @Dingus for -11 bytes and forcing me to do more research on hashes.

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

Perl 5 -p, 20 bytes

s/\(/
/g;s/\)/ -> /g

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Nice! You can save another 3 bytes using y;(;\n too: Try it online! \$\endgroup\$ Commented Mar 28 at 19:31
5
\$\begingroup\$

05AB1E, 8 bytes

¦'(¡')δ¡

Try it online or verify all test cases.

Explanation:

¦         # Remove the first "("-character of the (implicit) input-string
 '(¡     '# Then split on all remaining "("
      δ   # Map over each substring:
    ') ¡ '#  Split on ")"
          # (after which the list of pairs is output implicitly as result)
\$\endgroup\$
5
\$\begingroup\$

Haskell, 64 60 bytes

-4 bytes thanks to Wheat Wizard.

g=span(>'*')
f""=[]
f(_:s)|(a,_:b)<-g s,(c,d)<-g b=(a,c):f d

Try it online!

Invalid (but cooler) solution, 55 bytes

f""=[]
f(_:s)|[(a,_:b)]<-lex s,[(c,d)]<-lex b=(a,c):f d

Try it online!

Relies heavily on the built-in lex function that lexes Haskell lexemes. That means it almost works for the challenge at hand but it fails because it lexes anything that starts with a digit and ends with a letter as two different tokens, i.e. 337n as 337 and n.

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

JavaScript (V8), 56 bytes

x=>x.replace(/.(.*?)\)([^(]*)/g,(_,a,b)=>s[a]=b,s={})&&s

Try it online!

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

APL+WIN, 23 bytes

Prompts for string.

((+\m∊'()')⊂m←⎕)~¨⊂'()'

Try it online! Thanks to Dyalog Classic

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

Vyxal 3, 7 bytes

'(÷')÷Ḣ

Try it Online! port of vyxal 2

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

Jelly, 8 bytes

ṣ”(Ḋṣ€”)

Try It Online!

Returns output as a list of key-value pairs.

Explanation

ṣ”(Ḋṣ€”)    Main Link
ṣ”(         Split at "("
   Ḋ        Drop the first element
    ṣ€”)    Split each line at ")"
\$\endgroup\$
3
\$\begingroup\$

Java 8, 174 172 bytes

import java.util.*; s->{HashMap<String,String>c=new HashMap<String,String>();for(String a:s.split("\\(")){String[]b=a.split("\\)");if(b.length>1)c.put(b[0],b[1]);}return c;}

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ You can remove a lot of spaces and save many more bytes that way \$\endgroup\$
    – corvus_192
    Commented Mar 27 at 14:59
  • \$\begingroup\$ @corvus_192 I did it! thanks <3 \$\endgroup\$ Commented Mar 27 at 15:05
  • 1
    \$\begingroup\$ I'm afraid imports count towards the byte-count, so you'll have to add the cost of import java.util.*; for the HashMap. As for some golfs in Java 8: import java.util.*;s->{Map c=new HashMap();for(String a:s.substring(1).split("\\(")){String[]b=a.split("\\)");c.put(b[0],b[1]);}return c;}. Using Java 11+, you can also use var instead: s->{var c=new java.util.HashMap();for(var a:s.substring(1).split("\\(")){var b=a.split("\\)");c.put(b[0],b[1]);}return c;} - 122 bytes \$\endgroup\$ Commented Mar 27 at 15:14
  • \$\begingroup\$ @KevinCruijssen I've added import java.util.* towards the byte-count, thanks for let me know! \$\endgroup\$ Commented Mar 27 at 15:42
  • \$\begingroup\$ You can use the double-brace: s->{return new HashMap(){{for(String a:s.split("\\(")){String[]b=a.split("\\)");if(b.length>1)put(b[0],b[1]);}}};} \$\endgroup\$
    – G B
    Commented Mar 30 at 5:55
3
\$\begingroup\$

K (ngn/k) 14 bytes

!/+1_")"\'"("\

Try it here.

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

Uiua SBCS, 14 13 bytes

↯∞_2⊜□¬∊,"()"

Try it!

-1 thanks to RomanPro100

↯∞_2⊜□¬∊,"()"
       ∊,"()"   # mask of parentheses
      ¬         # invert
    ⊜□          # partition by box
↯∞_2            # reshape into pairs
\$\endgroup\$
1
  • 1
    \$\begingroup\$ It can be shorter if you replace :"()". with ,"()" \$\endgroup\$ Commented Mar 28 at 8:25
2
\$\begingroup\$

Swift, 53 bytes

let f={($0+"").split{$0=="("}.map{$0.split{$0==")"}}}

Try it online!

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

JavaScript (ES6), 55 bytes

s=>s.split`(`.map(s=>o[([,v]=s.split`)`)[0]]=v,o={})&&o

Try it online!


JavaScript (ES6), 59 bytes

An attempt at a recursive approach.

f=(s,[a,b,...c]=s.match(/[^()]+/g))=>a?{[a]:b,...f(s,c)}:{}

Try it online!

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

Google Sheets, 58 bytes

=WRAPROWS(SPLIT(REGEXREPLACE(A1,"([()])0","$1'0"),"()"),2)

The formula would be as simple as:

=WRAPROWS(SPLIT(A1,"()"),2) // 27 bytes

If GS didn't automatically cast the strings to numbers removing leading \$0\$s.

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

Pip -p, 7 bytes

<>a@+XW

Outputs a list of [key;value] pairs. Attempt This Online!

Explanation

<>a@+XW
     XW ; Regex `\w` (word character: either alphanumeric or underscore)
    +   ; Apply + quantifier (match 1 or more)
  a@    ; Find all matches in command-line argument
<>      ; Group into pairs of elements
\$\endgroup\$
2
\$\begingroup\$

Java (OpenJDK 8), 101 bytes

s->java.util.Arrays.stream(s.split("\\(")).skip(1).map(x->x.split("\\)")).toArray(n->new String[n][])

Try it online!

Ungolfed:

s -> java.util.Arrays.stream(s.split("\\("))
    .skip(1)
    .map(x -> x.split("\\)"))
    .toArray(n -> new String[n][])
\$\endgroup\$
1
  • 1
    \$\begingroup\$ n->new String[n][] can be String[][]::new for -3 bytes \$\endgroup\$ Commented Mar 29 at 9:50
2
\$\begingroup\$

Python 3, 49 bytes

lambda x:dict(re.findall(2*".(\w+)",x))
import re

Try it online!

Returns a dict. Test harness borrowed from @Mukundan314.

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

Haskell + hgl, 21 17 bytes

sL ')'<<tl<sL '('

Attempt This Online!

\$\endgroup\$
3
  • \$\begingroup\$ map is exported as m, and (.) is renamed to (<) for technical reasons. This can be: sL ')'<<tl<sL '(' \$\endgroup\$
    – Wheat Wizard
    Commented Mar 28 at 0:19
  • \$\begingroup\$ On newer versions of hgl you can also do sa")"<<tl<sa")", but sa isn't available on ato yet. \$\endgroup\$
    – Wheat Wizard
    Commented Mar 28 at 0:31
  • \$\begingroup\$ @WheatWizard Thanks \$\endgroup\$
    – corvus_192
    Commented Mar 29 at 10:34
0
\$\begingroup\$

Perl 5 + -050lF/\)/ -M5.10.0, 15 bytes

An alternative solution to @Xcali's great answer.

$,=' -> ';say@F

Try it online!

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

Kotlin, 35 bytes

{split('(',')').drop(1).chunked(2)}

Try on playground!

I mean, they are associated, you can find the value for a key:

val map = "(01)99012345670019(10)Ab1234(3102)00122515190521(337n)001234".function()

fun getValue(key: String) = map.find { it[0] == key }?.get(1)
println(getValue("10")) // outputs "Ab1234"
\$\endgroup\$

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