15
\$\begingroup\$

!!!Batch is another derivative of the Windows Batch programming language, its wiki is here

Your challenge is to create an compiler/translator that reads a !!!Batch program and returns a Windows Batch program.

In !!!Batch each token braced in two question marks like ?!!!? is converted to another ASCII character, like '?!?' -> 'a' and so on below, and after decoding the whole !!!Batch program it is a Windows batch program

'?!?', 'a'
'?!!?', 'b'
'?!!!?', 'c'
'?!!!!?', 'd'
'?!!!!!?', 'e'
'?!!!!!!?', 'f'
'?!!!!!!!?', 'g'
'?!!!!!!!!?', 'h'
'?!!!!!!!!!?', 'i'
'?!!!!!!!!!!?', 'j'
'?!!!!!!!!!!!?', 'k'
'?!!!!!!!!!!!!?', 'l'
'?!!!!!!!!!!!!!?', 'm'
'?!!!!!!!!!!!!!!?', 'n'
'?!!!!!!!!!!!!!!!?', 'o'
'?!!!!!!!!!!!!!!!!?', 'p'
'?!!!!!!!!!!!!!!!!!?', 'q'
'?!!!!!!!!!!!!!!!!!!?', 'r'
'?!!!!!!!!!!!!!!!!!!!?', 's'
'?!!!!!!!!!!!!!!!!!!!!?', 't'
'?!!!!!!!!!!!!!!!!!!!!!?', 'u'
'?!!!!!!!!!!!!!!!!!!!!!!?', 'v'
'?!!!!!!!!!!!!!!!!!!!!!!!?', 'w'
'?!!!!!!!!!!!!!!!!!!!!!!!!?', 'x'
'?!!!!!!!!!!!!!!!!!!!!!!!!!?', 'y'
'?!!!!!!!!!!!!!!!!!!!!!!!!!!?', 'z'
'?!-?', '&'
'?!!-?', ' '
'?!!!-?', '?'
'?!!!!-?', '!'
'?!!!!!-?', '%'
'?!!!!!!-?', '/'
'?!!!!!!!-?', '.'
'?!!!!!!!!-?', ':'
'?!!!!!!!!!-?', '0'
'?!!!!!!!!!!-?', '1'
'?!!!!!!!!!!!-?', '2'
'?!!!!!!!!!!!!-?', '3'
'?!!!!!!!!!!!!!-?', '4'
'?!!!!!!!!!!!!!!-?', '5'
'?!!!!!!!!!!!!!!!-?', '6'
'?!!!!!!!!!!!!!!!!-?', '7'
'?!!!!!!!!!!!!!!!!!-?', '8'
'?!!!!!!!!!!!!!!!!!!-?', '9'
'?!!!!!!!!!!!!!!!!!!!-?', '='
'?!!!!!!!!!!!!!!!!!!!!-?', '+'
'?!!!!!!!!!!!!!!!!!!!!!-?', '-'
'?!!!!!!!!!!!!!!!!!!!!!!-?', '<'
'?!!!!!!!!!!!!!!!!!!!!!!!-?', '>'
'?!!!!!!!!!!!!!!!!!!!!!!!!-?', '@'
'?!!!!!!!!!!!!!!!!!!!!!!!!!-?', '*'
'?!+?', 'A'
'?!!+?', 'B'
'?!!!+?', 'C'
'?!!!!+?', 'D'
'?!!!!!+?', 'E'
'?!!!!!!+?', 'F'
'?!!!!!!!+?', 'G'
'?!!!!!!!!+?', 'H'
'?!!!!!!!!!+?', 'I'
'?!!!!!!!!!!+?', 'J'
'?!!!!!!!!!!!+?', 'K'
'?!!!!!!!!!!!!+?', 'L'
'?!!!!!!!!!!!!!+?', 'M'
'?!!!!!!!!!!!!!!+?', 'N'
'?!!!!!!!!!!!!!!!+?', 'O'
'?!!!!!!!!!!!!!!!!+?', 'P'
'?!!!!!!!!!!!!!!!!!+?', 'Q'
'?!!!!!!!!!!!!!!!!!!+?', 'R'
'?!!!!!!!!!!!!!!!!!!!+?', 'S'
'?!!!!!!!!!!!!!!!!!!!!+?', 'T'
'?!!!!!!!!!!!!!!!!!!!!!+?', 'U'
'?!!!!!!!!!!!!!!!!!!!!!!+?', 'V'
'?!!!!!!!!!!!!!!!!!!!!!!!+?', 'W'
'?!!!!!!!!!!!!!!!!!!!!!!!!+?', 'X'
'?!!!!!!!!!!!!!!!!!!!!!!!!!+?', 'Y'
'?!!!!!!!!!!!!!!!!!!!!!!!!!!+?', 'Z'

Example Input:

?!!!!!!!!!!!!!!!!??!!!!!!!!!??!!!!!!!!!!!!!!??!!!!!!!??!!-??!!!!!!!??!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!??!!!!!!!??!!!!!!!!!!!!??!!!!!??!!!!!!!-??!!!??!!!!!!!!!!!!!!!??!!!!!!!!!!!!!?

Example output:

ping google.com

**How the output?

First break down into parts:

?!!!!!!!!!!!!!!!!? -> 'p'
?!!!!!!!!!? - 'i'

and so on

  • For more clarification, please visit the Wiki or ask me here.

  • Standard loopholes apply

  • This is , shortest code wins

An un-golfed sample compiler in python 2, from the Wiki page

s = open(raw_input("Run Script: "), 'r').read()
s = s.replace('?!?', 'a')
s = s.replace('?!!?', 'b')
s = s.replace('?!!!?', 'c')
s = s.replace('?!!!!?', 'd')
s = s.replace('?!!!!!?', 'e')
s = s.replace('?!!!!!!?', 'f')
s = s.replace('?!!!!!!!?', 'g')
s = s.replace('?!!!!!!!!?', 'h')
s = s.replace('?!!!!!!!!!?', 'i')
s = s.replace('?!!!!!!!!!!?', 'j')
s = s.replace('?!!!!!!!!!!!?', 'k')
s = s.replace('?!!!!!!!!!!!!?', 'l')
s = s.replace('?!!!!!!!!!!!!!?', 'm')
s = s.replace('?!!!!!!!!!!!!!!?', 'n')
s = s.replace('?!!!!!!!!!!!!!!!?', 'o')
s = s.replace('?!!!!!!!!!!!!!!!!?', 'p')
s = s.replace('?!!!!!!!!!!!!!!!!!?', 'q')
s = s.replace('?!!!!!!!!!!!!!!!!!!?', 'r')
s = s.replace('?!!!!!!!!!!!!!!!!!!!?', 's')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!?', 't')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!?', 'u')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!?', 'v')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!!?', 'w')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!!!?', 'x')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!!!!?', 'y')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!!!!!?', 'z')
s = s.replace('?!-?', '&')
s = s.replace('?!!-?', ' ')
s = s.replace('?!!!-?', '?')
s = s.replace('?!!!!-?', '!')
s = s.replace('?!!!!!-?', '%')
s = s.replace('?!!!!!!-?', '/')
s = s.replace('?!!!!!!!-?', '.')
s = s.replace('?!!!!!!!!-?', ':')
s = s.replace('?!!!!!!!!!-?', '0')
s = s.replace('?!!!!!!!!!!-?', '1')
s = s.replace('?!!!!!!!!!!!-?', '2')
s = s.replace('?!!!!!!!!!!!!-?', '3')
s = s.replace('?!!!!!!!!!!!!!-?', '4')
s = s.replace('?!!!!!!!!!!!!!!-?', '5')
s = s.replace('?!!!!!!!!!!!!!!!-?', '6')
s = s.replace('?!!!!!!!!!!!!!!!!-?', '7')
s = s.replace('?!!!!!!!!!!!!!!!!!-?', '8')
s = s.replace('?!!!!!!!!!!!!!!!!!!-?', '9')
s = s.replace('?!!!!!!!!!!!!!!!!!!!-?', '=')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!-?', '+')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!-?', '-')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!-?', '<')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!!-?', '>')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!!!-?', '@')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!!!!-?', '*')
s = s.replace('?!+?', 'A')
s = s.replace('?!!+?', 'B')
s = s.replace('?!!!+?', 'C')
s = s.replace('?!!!!+?', 'D')
s = s.replace('?!!!!!+?', 'E')
s = s.replace('?!!!!!!+?', 'F')
s = s.replace('?!!!!!!!+?', 'G')
s = s.replace('?!!!!!!!!+?', 'H')
s = s.replace('?!!!!!!!!!+?', 'I')
s = s.replace('?!!!!!!!!!!+?', 'J')
s = s.replace('?!!!!!!!!!!!+?', 'K')
s = s.replace('?!!!!!!!!!!!!+?', 'L')
s = s.replace('?!!!!!!!!!!!!!+?', 'M')
s = s.replace('?!!!!!!!!!!!!!!+?', 'N')
s = s.replace('?!!!!!!!!!!!!!!!+?', 'O')
s = s.replace('?!!!!!!!!!!!!!!!!+?', 'P')
s = s.replace('?!!!!!!!!!!!!!!!!!+?', 'Q')
s = s.replace('?!!!!!!!!!!!!!!!!!!+?', 'R')
s = s.replace('?!!!!!!!!!!!!!!!!!!!+?', 'S')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!+?', 'T')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!+?', 'U')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!+?', 'V')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!!+?', 'W')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!!!+?', 'X')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!!!!+?', 'Y')
s = s.replace('?!!!!!!!!!!!!!!!!!!!!!!!!!!+?', 'Z')
print s
\$\endgroup\$
14
  • \$\begingroup\$ “each character “ sounds incorrect, can you say “each token” or something like that? \$\endgroup\$ – user Feb 18 at 4:16
  • \$\begingroup\$ @user clarified it see edit \$\endgroup\$ – wasif Feb 18 at 4:19
  • 3
    \$\begingroup\$ @user202729 input is guaranteed to be valid \$\endgroup\$ – wasif Feb 18 at 4:44
  • 7
    \$\begingroup\$ The Python 2 example is wrong. For input ?!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!-??!!!!!!!!!!!!!!!!!!!!!-??!!!-? it should output ?!!!!!!!!!!!!!!!!!!!!!!!!-? but instead it outputs @ \$\endgroup\$ – pxeger Feb 18 at 8:56
  • 1
    \$\begingroup\$ Suggest to add any testcases with upper case letters. \$\endgroup\$ – tsh Feb 18 at 9:20

11 Answers 11

5
\$\begingroup\$

JavaScript, 118 bytes

s=>s.replace(/.+?\?/g,x=>x[i=x.length-2]>','?'& ?!%/.:0123456789=+-<>@*'[i-2]:String.fromCharCode(x[i]<'+'?96+i:63+i))

Try it online!


JavaScript, 118 bytes

s=>s.replace(/.!+(.??)\?/g,(x,y)=>(i=x.length,y>','?'& ?!%/.:0123456789=+-<>@*'[i-4]:String.fromCharCode(61+i+33*!y)))

Try it online!

Quite trivial answer.


Thanks to Arnauld, changing String.fromCharCode(n) into Buffer([n]) under Node.js environment may save 11 bytes and results 107 bytes.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You can use Buffer([n]) instead of String.fromCharCode(n). \$\endgroup\$ – Arnauld Feb 18 at 9:51
  • \$\begingroup\$ @Arnauld I'm not familiar with Node. I just want to post an answer in JavaScript. And TIO helps me add "(Node.js)" in the language name. I will add the Buffer([n]) trick in the post body but keeps the submission as is (as pure javascript). \$\endgroup\$ – tsh Feb 19 at 2:03
4
\$\begingroup\$

05AB1E, 41 bytes

¬¡õKεθ„!+skADužh"& ?!%/.:ÿ=+-<>@*")ćèyć¢è

Output as a list of characters.

Try it online (the footer is to join the resulting list to pretty-print as string; feel free to remove it to see the actual list output).

Explanation:

¬             # Push the first character of the (implicit) input-string: "?"
 ¡            # Split the input on that character
  õK          # Remove all empty strings
    ε         # Map over each string:
     θ        #  Pop and push its last character
      „!+     #  Push string "!+"
         sk   #  Get the index of the last character in this string,
              #  (-1 if not found, for the "-")
     A        #  Push the lowercase alphabet
      Du      #  Create an uppercase copy
        žh    #  Push builtin "0123456789"
          "& ?!%/.:ÿ=+-<>@*"
              #  Push this string, where the `ÿ` is automatically filled with 0123456789
     )        #  Wrap all values into a list
      ć       #  Extract head; pop and push remainder-list and first item separated
       è      #  Use this index to (0-based modulair) index into the triplet
              #  (where the -1 for "-" will index into the last item)
        y     #  Push the current string again
         ć    #  Extract its head as well: "!"
          ¢   #  Count how many times it occurs in the remainder-string
           è  #  0-based index this into the string
              # (after the map, the resulting list of characters is output implicitly)

Unfortunately the "& ?!%/.:0123456789=+-<>@*" is a bit too irregular to compress. The shortest alternative I could find for this straight-forward string was žQ33£S•1δÁεöI‡β₆¡ÙÞ‹f31•.I (žQ push printable ASCII builtin; 33£ leave just its first 33 characters; S convert it from a string to a list of characters; •1δÁεöI‡β₆¡ÙÞ‹f30•.I get the 1586478393328926104294588200482791040th permutation of this list), which is 6 bytes longer.

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

Stax, 53 46 bytes

é♫▼V0⌂Ä╟ì⌡(Φzf■£┘╔╣T╘K*╪☻w²¥íÑ╧zv-¼Ö╨◘P♦ε♦íäq*

Run and debug it

I wasn't able to find an expression that matches the symbols, so those are hardcoded (and take a lot of space.)

Explanation

'?/{f{%_rh.-+I{"@*& ?!%/.:"Vd+"=+-<>"+@}{63+}{96+}3l@!m

'?/ split on ?

{f remove empty lists

{..m map the strings to:

% push the length of the match

_ push the match again

rDh get the second to last character

.-+I index of that in "-+"

@! execute the corresponding block for the index:

{"<>@*& ?!%/.:"Vd+"=+-"+@}{61+}{94+}3l create a list of 3 blocks

{63+} for +, add 63 to the length

{"@*& ?!%/.:"Vd+"=+-<>"+@} for -, index into <>@*& ?!%/.:0123456789=+- using the length(modular)

{96+} otherwise add 91

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

C (gcc), 142 139 130 115 bytes

Thanks to tsh for the -3 and gastropher for the -9.

The function uses a state machine to determine the boundaries of each token:

  • loop: load the next input character until the end of the string
  • state 0 (initial ?): clear the counter, then go to state 1
  • state 1 (!, +, - or terminating ?): increment on a !, otherwise print the character (adjusted count by 96 [?] or 64 [+], or indexed symbol [-]) and go to state 0, incrementing the input string if a + or -.
t,c,n;f(char*s){for(;c=*s++;)n=t?c-33?t=!putchar(c-63?s++,c-43?" & ?!%/.:0123456789=+-<>@*"[n]:n+64:n+96):n+1:t++;}

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ I believe, according to the rules, you can remove the t=0 in for(t=0;c=*s++;) since we can assume global variable used in function will never be modified outside. Global variables are initialed to 0 by default. And the function reset to 0 after execute. So the function is still reusable without it. \$\endgroup\$ – tsh Feb 18 at 10:19
  • \$\begingroup\$ 130 bytes \$\endgroup\$ – gastropner Feb 18 at 22:27
3
\$\begingroup\$

Retina 0.8.2, 94 94 bytes

\?!
!
!\?
a
!\+\?
A
-

!{5}\?
%
+T`_o`lL%/.:d=+\-<>@*!_`!(?![?!]).
!\?
$& &
!(?=..(.))!*...
$1

Try it online! Edit: +1 byte to fix a bug but -1 thanks to @tsh. Explanation:

\?!
!

Remove the ? at the start of a token.

!\?
a

?!?, which is now !?, translates to a.

!\+\?
A

?!+?, which is now !+?, translates to A.

-

Get rid of the -s.

!{5}\?
%

?!!!!!-?, which is now !!!!!?, translates to %.

+T`_o`lL%/.:d=+\-<>@*!_`!(?![?!]).

For each additional !, cycle the following character; letters get incremented, while d represents digits which nestle among the symbols.

!\?
$& &

The remaining !?s represent one of !, ?, and & in reverse order, depending on the number of preceding !s. Add the other characters so that the correct decode can be selected.

!(?=..(.))!*...
$1

Decode the remaining !?, !!?, !!!? and !!!!? sequences appropriately.

\$\endgroup\$
1
  • \$\begingroup\$ !+\? should be !\+\? (+1 byte), but !!!!!\? may be !{5}\? (-1 byte). \$\endgroup\$ – tsh Feb 19 at 2:11
3
\$\begingroup\$

Julia, 108 104 bytes

-4 bytes thanks to tsh's better regex

s->replace(s,r".+?\?"=>x->["_& ?!%/.:0123456789=+-<>@*_"[(l=length(x))-2],l+'^',l+'='][('.'-x[l-1])%11])

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I don't know Julia, but maybe use regex r".+?\?" replace r"\?!+.*?\?" may helpful to your solution. \$\endgroup\$ – tsh Feb 19 at 1:58
3
\$\begingroup\$

Perl 5 -n, 96 84 83 bytes

say map/-/?substr'  & ?!%/.:0123456789=+-<>@*',y///c,1:chr/!$/*32+64+y///c,/[^?]+/g

Try it online!

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

Red, 164 158 bytes

func[s][r: copy""parse s[any["?"(n: 0)any["!"(n: n + 1)]["+?"(c: to sp 64 +
n)|"-?"(c: pick"& ?!%/.:0123456789=+-<>@*"n)|"?"(c: to sp 96 + n)](append r c)]]r]

Try it online!

Old, non-Parse solution, 169 bytes

func[s][r: copy""foreach c extract next split s"?"2[d: length? c append r switch
to 1 last c[33[to sp 96 + d]43[to sp 63 + d]45[pick"& ?!%/.:0123456789=+-<>@*"d - 1]]]r]

Try it online!

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

Python 2, 191 161 133 bytes

-30 Thanks Kaddath! -28 Thanks tsh!

for e in input()[1:-1].split("??"):print(end={"!":chr(len(e)+96),"+":chr(len(e)+63),"-":('<>& ?!%/.:0123456789=+'*9)[len(e)]}[e[-1]])

Try it online!

Explanation

(Will update this later)

Ungolfed:

a = input[1:-1].split("??") # Get every part
t = "" # Output string
for e in a: # Iterates over a
 f,l,p=chr,len(e),e[-1] # They are used many times, this is for shorter code
 exec({
  "!":"t+=f(l+96)",                       # if ends with "!", get the l+96 -th ASCII char
  "+":"t+=f(l+63)",                       # ends with "+", get the l+63 -th
  "-":"t+='@*& ?!%/.:0123456789=+<>'[l]"  # hard-coded string
 }[p])
print t # print the result
\$\endgroup\$
6
  • \$\begingroup\$ I don't know much Python but I think you can golf this code more by removing some whitespace. The general rules for output also say that you can either output the result directly, or have a function that returns the result, so you're not obliged to output the result in a function if it's shorter to return it. I recommend also Tips for golfing in Python \$\endgroup\$ – Kaddath Feb 18 at 8:45
  • \$\begingroup\$ print is 1 byte shorter than return, yes.@Kaddath And thanks for your suggestion. \$\endgroup\$ – SketchySketch Feb 18 at 9:30
  • \$\begingroup\$ Yes I checked and your code seems not compatible with implicit return, but if you print directly you don't need the function then \$\endgroup\$ – Kaddath Feb 18 at 9:34
  • \$\begingroup\$ 133 bytes by switch to Python 3, remove exec, and some line breaks: for e in input()[1:-1].split("??"):print(end={"!":chr(len(e)+96),"+":chr(len(e)+63),"-":('<>& ?!%/.:0123456789=+'*9)[len(e)]}[e[-1]]) \$\endgroup\$ – tsh Feb 19 at 2:24
1
\$\begingroup\$

Charcoal, 44 bytes

⭆⪪S?⎇№ι!§⎇№ι-”‴"μ⮌w7L⁴Vp#ωδk4θO(”⎇№ι+αβ⊖№ι!ι

Try it online! Link is to verbose version of code. Explanation:

⭆⪪S?

Split the input on ?s and map over each substring.

⎇№ι!

If this substring contains a !, then...

§⎇№ι-”‴"μ⮌w7L⁴Vp#ωδk4θO(”⎇№ι+αβ⊖№ι!

... count the number of !s and use this to index into either the compressed string of non-alphabetic characters or the upper or lower case alphabet depending on whether there is a - or + or not.

ι

Otherwise leave the substring unchanged.

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

JavaScript (Node.js), 125 bytes

s=>s.split`?`.map(a=>(b=a.length)?(z=a.slice(-1))==`-`?'& ?!%/.:0123456789=+-<>@*'[b-2]:Buffer([b+(63*z==`+`||96)]):a).join``

Try it online!

s.split`?`         splits the string at the char ?, results in an array
.map(a=>           pass item n in array to function and replace item with the return
    (b=a.length)?...            if a is not empty do ...
        a.slice(-1)==`-`?...     if last char in a is - do ...
            '& ?!%/.:0123456789=+-<>@*'[b-2]    get character at index
        :         else
        Buffer(b+(63*z==`+`||96))   character from code
    :a                 else return a
).join``            array to string

```
\$\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.