Skip to main content
added 106 characters in body
Source Link
Conor O'Brien
  • 40.2k
  • 3
  • 91
  • 180

C (gcc) (no builtins), 147147 143 bytes

4 bytes saved thanks to ceilingcat!

i,m,c,q,w;f(char*s){for(i=m=w=0;c=s[i]%9;i++)if(c-1?c-4?w=w*2+w+=w-~c%3,++m==4:(q=i,m=w=0):0)for(s[q]=w-2&&w<9?'>'62:'<';q++<i;60;q++<i;)s[q]=1;s=*s%3-1?*s:f(s);}

Try it online!Try it online!

Function that takes a null-terminated char array as input, and returns a char (int).

Here's a visualization of how it works:

(((>>>)<<)(<(<><)<)((<<(<<<))>(>(><>)<)))
((>....<<)(<<....<)((<<<....)>(>>....<)))
(>........<........(<........><........))
(>........<........<....................)
>........................................

(In the code, it uses 0x01 instead of ., but due to the modulus, they're equivalent even in data representation.)

Essentially it scans the code looking for instances of (data), where data consists of substring of 3 characters, except '.' and '('. (4, in the code, since it tracks the ) as the 4th character.) The program keeps track of the start of this string (q) and a binary representation of the visited characters (w). If we consider '>' to be equivalent to the binary 1, and '<' the binary 0, we simply look at a table of what the results of the binary strings should be. As it turns out, for q=1,4,5,6, the answer is '<', and '>' otherwise. Thus, w-1&&w<5 is a sufficient determiner. (In fact, since we keep track of ) as part of this binary string, we have to consider that everything is doubled, and for no byte cost, we can modify this formula to obtain the w-2&&w<9.)

After we determine what the result should be, we replace the initial ( with the result, and all subsequent characters with .. Then, so long as the initial character of the string is (, we repeat our function. This allows us to skip moving the string around, which, in my head, should save bytes, but I haven't tested the alternative.

Started working on this before I saw the existing (much shorter) C answer. But I enjoyed this nonetheless.

C (gcc) (no builtins), 147 bytes

i,m,c,q,w;f(char*s){for(i=m=w=0;c=s[i]%9;i++)if(c-1?c-4?w=w*2+-~c%3,++m==4:(q=i,m=w=0):0)for(s[q]=w-2&&w<9?'>':'<';q++<i;)s[q]=1;s=*s%3-1?*s:f(s);}

Try it online!

Function that takes a null-terminated char array as input, and returns a char (int).

Here's a visualization of how it works:

(((>>>)<<)(<(<><)<)((<<(<<<))>(>(><>)<)))
((>....<<)(<<....<)((<<<....)>(>>....<)))
(>........<........(<........><........))
(>........<........<....................)
>........................................

(In the code, it uses 0x01 instead of ., but due to the modulus, they're equivalent even in data representation.)

Essentially it scans the code looking for instances of (data), where data consists of substring of 3 characters, except '.' and '('. (4, in the code, since it tracks the ) as the 4th character.) The program keeps track of the start of this string (q) and a binary representation of the visited characters (w). If we consider '>' to be equivalent to the binary 1, and '<' the binary 0, we simply look at a table of what the results of the binary strings should be. As it turns out, for q=1,4,5,6, the answer is '<', and '>' otherwise. Thus, w-1&&w<5 is a sufficient determiner. (In fact, since we keep track of ) as part of this binary string, we have to consider that everything is doubled, and for no byte cost, we can modify this formula to obtain the w-2&&w<9.)

After we determine what the result should be, we replace the initial ( with the result, and all subsequent characters with .. Then, so long as the initial character of the string is (, we repeat our function. This allows us to skip moving the string around, which, in my head, should save bytes, but I haven't tested the alternative.

Started working on this before I saw the existing (much shorter) C answer. But I enjoyed this nonetheless.

C (gcc) (no builtins), 147 143 bytes

4 bytes saved thanks to ceilingcat!

i,m,c,q,w;f(char*s){for(i=m=w=0;c=s[i]%9;i++)if(c-1?c-4?w+=w-~c%3,++m==4:(q=i,m=w=0):0)for(s[q]=w-2&&w<9?62:60;q++<i;)s[q]=1;s=*s%3-1?*s:f(s);}

Try it online!

Function that takes a null-terminated char array as input, and returns a char (int).

Here's a visualization of how it works:

(((>>>)<<)(<(<><)<)((<<(<<<))>(>(><>)<)))
((>....<<)(<<....<)((<<<....)>(>>....<)))
(>........<........(<........><........))
(>........<........<....................)
>........................................

(In the code, it uses 0x01 instead of ., but due to the modulus, they're equivalent even in data representation.)

Essentially it scans the code looking for instances of (data), where data consists of substring of 3 characters, except '.' and '('. (4, in the code, since it tracks the ) as the 4th character.) The program keeps track of the start of this string (q) and a binary representation of the visited characters (w). If we consider '>' to be equivalent to the binary 1, and '<' the binary 0, we simply look at a table of what the results of the binary strings should be. As it turns out, for q=1,4,5,6, the answer is '<', and '>' otherwise. Thus, w-1&&w<5 is a sufficient determiner. (In fact, since we keep track of ) as part of this binary string, we have to consider that everything is doubled, and for no byte cost, we can modify this formula to obtain the w-2&&w<9.)

After we determine what the result should be, we replace the initial ( with the result, and all subsequent characters with .. Then, so long as the initial character of the string is (, we repeat our function. This allows us to skip moving the string around, which, in my head, should save bytes, but I haven't tested the alternative.

Started working on this before I saw the existing (much shorter) C answer. But I enjoyed this nonetheless.

Source Link
Conor O'Brien
  • 40.2k
  • 3
  • 91
  • 180

C (gcc) (no builtins), 147 bytes

i,m,c,q,w;f(char*s){for(i=m=w=0;c=s[i]%9;i++)if(c-1?c-4?w=w*2+-~c%3,++m==4:(q=i,m=w=0):0)for(s[q]=w-2&&w<9?'>':'<';q++<i;)s[q]=1;s=*s%3-1?*s:f(s);}

Try it online!

Function that takes a null-terminated char array as input, and returns a char (int).

Here's a visualization of how it works:

(((>>>)<<)(<(<><)<)((<<(<<<))>(>(><>)<)))
((>....<<)(<<....<)((<<<....)>(>>....<)))
(>........<........(<........><........))
(>........<........<....................)
>........................................

(In the code, it uses 0x01 instead of ., but due to the modulus, they're equivalent even in data representation.)

Essentially it scans the code looking for instances of (data), where data consists of substring of 3 characters, except '.' and '('. (4, in the code, since it tracks the ) as the 4th character.) The program keeps track of the start of this string (q) and a binary representation of the visited characters (w). If we consider '>' to be equivalent to the binary 1, and '<' the binary 0, we simply look at a table of what the results of the binary strings should be. As it turns out, for q=1,4,5,6, the answer is '<', and '>' otherwise. Thus, w-1&&w<5 is a sufficient determiner. (In fact, since we keep track of ) as part of this binary string, we have to consider that everything is doubled, and for no byte cost, we can modify this formula to obtain the w-2&&w<9.)

After we determine what the result should be, we replace the initial ( with the result, and all subsequent characters with .. Then, so long as the initial character of the string is (, we repeat our function. This allows us to skip moving the string around, which, in my head, should save bytes, but I haven't tested the alternative.

Started working on this before I saw the existing (much shorter) C answer. But I enjoyed this nonetheless.