62
\$\begingroup\$

I recently created a new language called ;# (pronounced "Semicolon Hash") which only has two commands:

; add one to the accumulator

# modulo the accumulator by 127, convert to ASCII character and output without a newline. After this, reset the accumulator to 0. Yes, 127 is correct.

Any other character is ignored. It has no effect on the accumulator and should do nothing.

Your task is to create an interpreter for this powerful language!

It should be either a full program or a function that will take a ;# program as input and produce the correct output.

Examples

Output: Hello, World!
Program: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#

Output: ;#
Program: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#

Output: 2d{ (unprintable characters here; should have 4 `\000` bytes between the `d` and the `{` and 3 after the `{`)
Program: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;hafh;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;f;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;###ffh#h#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ffea;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#au###h;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;h;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;o

Output: Fizz Buzz output
Program: link below

Output: !
Program: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#

Fizz Buzz up to 100

\$\endgroup\$
  • 1
    \$\begingroup\$ Is it acceptable if an interpreter doesn't terminate its execution at the end of the input but instead keeps looping indefinitely without producing extra output? \$\endgroup\$ – Leo May 22 '17 at 9:26
  • 5
    \$\begingroup\$ The second example makes me wonder about a program to encode a program to produce an output... recursive compilation! \$\endgroup\$ – frarugi87 May 22 '17 at 9:29
  • \$\begingroup\$ @Leo yes that's fine \$\endgroup\$ – caird coinheringaahing May 22 '17 at 14:46
  • 1
    \$\begingroup\$ @iamnotmaynard Semicolon Hash \$\endgroup\$ – caird coinheringaahing May 23 '17 at 15:09
  • 2
    \$\begingroup\$ Maybe Wink Hash would be easier to say \$\endgroup\$ – James Waldby - jwpat7 May 23 '17 at 17:42

105 Answers 105

20
\$\begingroup\$

Python 3, 69 68 bytes

-1 byte thanks to @WheatWizard

i=0
for c in input():
 i+=c==';'
 if'#'==c:print(end=chr(i%127));i=0

Try it online!

\$\endgroup\$
17
\$\begingroup\$

JavaScript (ES6), 76 82 80 bytes

s=>s.replace(/./g,c=>c=='#'?String.fromCharCode(a%(a=127)):(a+=(c==';'),''),a=0)

Demo

let f =

s=>s.replace(/./g,c=>c=='#'?String.fromCharCode(a%(a=127)):(a+=(c==';'),''),a=0)

console.log(JSON.stringify(f(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#")))
console.log(JSON.stringify(f(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#")))
console.log(JSON.stringify(f(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;hafh;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;f;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;###ffh#h#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ffea;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#au###h;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;h;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;o")))
console.log(JSON.stringify(f(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#")))

Recursive version, 82 77 bytes

Saved 5 bytes thanks to Neil

This one is likely to crash for large inputs such as the Fizz Buzz example.

f=([c,...s],a=0)=>c?c=='#'?String.fromCharCode(a%127)+f(s):f(s,a+(c==';')):""
\$\endgroup\$
  • \$\begingroup\$ I think f(s,a+(c==';')) might knock three bytes off your recursive version. \$\endgroup\$ – Neil May 22 '17 at 8:52
  • \$\begingroup\$ @Neil It actually saves 5 bytes. :-) \$\endgroup\$ – Arnauld May 22 '17 at 11:10
  • \$\begingroup\$ I feel really silly now. I originally had a buggy version, and subtracted 2 bytes to fix the bug. But I had miscounted and the buggy version actually saved 7 bytes... \$\endgroup\$ – Neil May 22 '17 at 11:23
12
\$\begingroup\$

Retina, 336 63 67 65 66 62 59 bytes

T`;#-ÿ`¯_
;{127}|;+$

(^|¯)
¯
+T`-~`_-`[^¯]
T\`¯`

Try it online!

Readable version using hypothetical escape syntax:

T`;#\x01-ÿ`\x01¯_
;{127}|;+$

(^|¯)\x01\x01
¯\x02
+T`\x01-~`_\x03-\x7f`[^\x01¯]\x01
T\`¯`

Does not print NUL bytes, because TIO doesn't allow them in the source code. Also prints an extra newline at the end, but I guess it can't do otherwise. Trailing newline suppressed thanks to @Leo.

-273 (!) bytes thanks to @ETHproductions.

-2 bytes thanks to @ovs.

-3 bytes thanks to @Neil. Check out their wonderful 34-byte solution.

\$\endgroup\$
  • 1
    \$\begingroup\$ Oh my word. But can you not save a thousand bytes with +T`\x01-~`_\x03-\x7f`[^\x01¯]\x01? (including the unprintables as single chars, of course) \$\endgroup\$ – ETHproductions May 21 '17 at 23:41
  • \$\begingroup\$ @ETHproductions Of course you can. Thank you! :) \$\endgroup\$ – eush77 May 21 '17 at 23:51
  • 1
    \$\begingroup\$ Currently the last letter is always in the output, even if there is no trailing # in the input. You can fix it by changing your second stage to (;{127}|;+$) \$\endgroup\$ – ovs May 22 '17 at 5:10
  • 1
    \$\begingroup\$ Do you need the +` on the third line? As you remove the entire match, there should be nothing left to replace in the second iteration. \$\endgroup\$ – ovs May 22 '17 at 9:14
  • 1
    \$\begingroup\$ I think I can do this in 34 bytes: T`;#\x01-ÿ`\x80\x7F_ \x80+$ (empty line) \+T`\x7Fo`\x01-\x80_`\x80[^\x80] (using hexadecimal escapes to represent unprintables). Outputs \x7F instead of nulls. \$\endgroup\$ – Neil May 22 '17 at 9:45
12
\$\begingroup\$

Java 8, 100 bytes

s->{int i=0;for(byte b:s.getBytes()){if(b==59)i++;if(b==35){System.out.print((char)(i%127));i=0;}}};

Try it online!

\$\endgroup\$
  • 3
    \$\begingroup\$ Welcome to the site! :) \$\endgroup\$ – DJMcMayhem May 22 '17 at 16:25
  • \$\begingroup\$ I added a link to an online interpreter with the FizzBuzz example for you (link text was too long to fit in a comment) \$\endgroup\$ – Jonathan Allan May 22 '17 at 20:26
  • \$\begingroup\$ Java uses UTF-16 for its programs. So, these aren't 100 bytes but 100 characters. \$\endgroup\$ – G.Broser says Reinstate Monica May 23 '17 at 12:50
  • 5
    \$\begingroup\$ @GeroldBroser Unicode is a character set: UTF-8 and UTF-16 are two encodings of that character set. ASCII source is perfectly valid as a Java program, and I have plenty of Java source files encoded in ASCII (which is also valid UTF-8, hence also a Unicode encoding). \$\endgroup\$ – user18932 May 23 '17 at 20:24
  • 1
    \$\begingroup\$ Entirely golfed, for 81 bytes as a Consumer<char[]>: s->{char i=0;for(int b:s){if(b==59)i++;if(b==35){System.out.print(i%=127);i=0;}}} \$\endgroup\$ – Olivier Grégoire Aug 11 '17 at 9:55
11
\$\begingroup\$

Japt, 18 bytes

®è'; %# d}'# ë ¯J

There's an unprintable \x7f char after %#. Test it online!

How it works

®   è'; %#   d}'# ë ¯  J
mZ{Zè'; %127 d}'# ë s0,J
                         // Implicit: operate on input string
mZ{           }'#        // Split the input at '#'s, and map each item Z to
   Zè';                  //   the number of semicolons in Z,
        %127             //   mod 127,
             d           //   turned into a character.
m              '#        // Rejoin the list on '#'. At this point the Hello, World! example
                         // would be "H#e#l#l#o#,# #W#o#r#l#d#!#" plus an null byte.
                  ë      // Take every other character. Eliminates the unnecessary '#'s. 
                    ¯J   // Slice off the trailing byte (could be anything if there are
                         // semicolons after the last '#').
                         // Implicit: output result of last expression
\$\endgroup\$
  • 1
    \$\begingroup\$ D'oh, should have checked the answers! Just spent some time on this only to find you'd beaten me to the punch. q'# ®è'; u# dì¯J also works for the same score. \$\endgroup\$ – Shaggy May 22 '17 at 10:35
11
\$\begingroup\$

Python, 65 bytes

This is a golf of this earlier answer.

lambda t:''.join(chr(x.count(';')%127)for x in t.split('#')[:-1])

Try it online! Python2

Try it online! Python3

Explanation

This is a pretty straightforward answer we determine how many ;s are between each # and print the chr mod 127. The only thing that might be a little bit strange is the [:-1]. We need to drop the last group because there will be no # after it.

For example

;;#;;;;#;;;;;#;;;

Will be split into

[';;',';;;;',';;;;;',';;;']

But we don't want the last ;;; because there is no # after it to print the value.

\$\endgroup\$
  • 1
    \$\begingroup\$ I was busy trying to get all tests in one TIO link. Was chr for chr except t and x. \$\endgroup\$ – Jonathan Allan May 21 '17 at 23:54
9
\$\begingroup\$

><>, 35 bytes

>i:0(?;:'#'=?v';'=?0
^   [0o%'␡'l~<

Try it online! Replace with 0x7F, ^?, or "delete".

Main loop

>i:0(?;:'#'=?v      
^            <

This takes a character of input (i), checks if its less than zero i.e. EOF (:0() and terminates the program if it is (?;). Otherwise, check if the input is equal to # (:'#'=). If it is, branch down and restart the loop (?v ... ^ ... <).

Counter logic

              ';'=?0
              

Check if the input is equal to ; (';'=). If it is, push a 0. Otherwise, do nothing. This restarts the main loop.

Printing logic

>       '#'=?v      
^   [0o%'␡'l~<

When the input character is #, pop the input off the stack (~), get the number of members on the stack (l), push 127 ('␡'), and take the modulus (%). Then, output it as a character (o) and start a new stack ([0). This "zeroes" out the counter. Then, the loop restarts.

\$\endgroup\$
9
\$\begingroup\$

Python 3, 69 Bytes

Improved, thanks to @Wheat Wizard, @Uriel

print(''.join(chr(s.count(';')%127)for s in input().split('#')[:-1]))
\$\endgroup\$
  • 3
    \$\begingroup\$ Welcome to Programming Puzzles and Code Golf! The objective here is to make the code as short as possible (in bytes), so you need to include the byte count in the header :). \$\endgroup\$ – Adnan May 21 '17 at 20:13
  • \$\begingroup\$ Thanks for explaining, didn't know that. I'll work on it then. \$\endgroup\$ – MrGeek May 21 '17 at 20:15
  • 2
    \$\begingroup\$ You can remove the space after the :s. \$\endgroup\$ – Pavel May 21 '17 at 21:02
  • 1
    \$\begingroup\$ I count 74 bytes. tio.run/nexus/… \$\endgroup\$ – Dennis May 21 '17 at 22:34
  • 2
    \$\begingroup\$ Also, ';'==c saves a space, but not using if statements at all would be even shorter. \$\endgroup\$ – Dennis May 21 '17 at 22:39
9
\$\begingroup\$

Röda, 44 39 38 bytes

5 bytes saved thanks to @fergusq

{(_/`#`)|{|d|d~="[^;]",""chr #d%127}_}

Try it online!

Anonymous function that takes the input from the stream.


If other characters do not have to be ignored, I get this:

Röda, 20 bytes

{(_/`#`)|chr #_%127}
\$\endgroup\$
8
\$\begingroup\$

Ruby, 41 35 34 characters

(40 34 33 characters code + 1 character command line option)

gsub(/.*?#/){putc$&.count ?;%127}

Thanks to:

  • Jordan for suggesting to use putc to not need explicit conversion with .chr (6 characters)
  • Kirill L. for finding the unnecessary parenthesis (1 character)

Sample run:

bash-4.4$ ruby -ne 'gsub(/.*?#/){putc$&.count ?;%127}' < '2d{.;#' | od -tad1
0000000    2  etb    d  nul  nul  nul  nul    {  nul  nul  nul
          50   23  100    0    0    0    0  123    0    0    0
0000013

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Doh. Although I done C in my early years, I completely forgot putc(). Thank you, @Jordan \$\endgroup\$ – manatwork Dec 16 '17 at 16:33
  • 1
    \$\begingroup\$ To my own surprise, you can actually drop parentheses after count to save a byte \$\endgroup\$ – Kirill L. Aug 10 '18 at 11:35
  • \$\begingroup\$ Nice catch, @KirillL., thank you. \$\endgroup\$ – manatwork Aug 10 '18 at 15:39
7
\$\begingroup\$

05AB1E, 16 15 14 bytes

Code:

'#¡¨ʒ';¢127%ç?

Explanation:

'#¡              # Split on hashtags
   ¨             # Remove the last element
    ʒ            # For each element (actually a hacky way, since this is a filter)
     ';¢         #   Count the number of occurences of ';'
        127%     #   Modulo by 127
            ç    #   Convert to char
             ?   #   Pop and print without a newline

Uses the 05AB1E-encoding. Try it online!

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

Jelly, 13 bytes

ṣ”#Ṗċ€”;%127Ọ

Try it online!

How it works

ṣ”#Ṗċ€”;%127Ọ  Main link. Argument: s (string)

ṣ”#            Split s at hashes.
   Ṗ           Pop; remove the last chunk.
    ċ€”;       Count the semicola in each chunk.
        %127   Take the counts modulo 127.
            Ọ  Unordinal; cast integers to characters.
\$\endgroup\$
  • 1
    \$\begingroup\$ The word semicola doesn't exist it's semicolons. \$\endgroup\$ – Erik the Outgolfer Jun 11 '17 at 17:51
  • \$\begingroup\$ @EriktheOutgolfer en.m.wiktionary.org/wiki/semicola \$\endgroup\$ – Dennis Jun 11 '17 at 17:52
  • \$\begingroup\$ Hmm, weird word. \$\endgroup\$ – Erik the Outgolfer Jun 11 '17 at 17:53
  • \$\begingroup\$ @EriktheOutgolfer Someone on Wiktionary was probably trying to make the Latin plural valid in English, but cola and semicola spellings should be proscribed. \$\endgroup\$ – Cœur Sep 9 '17 at 14:23
7
\$\begingroup\$

x86 machine code on MS-DOS - 29 bytes

00000000  31 d2 b4 01 cd 21 73 01  c3 3c 3b 75 06 42 80 fa  |1....!s..<;u.B..|
00000010  7f 74 ed 3c 23 75 eb b4  02 cd 21 eb e3           |.t.<#u....!..|
0000001d

Commented assembly:

bits 16
org 100h

start:
    xor dx,dx       ; reset dx (used as accumulator)
readch:
    mov ah,1
    int 21h         ; read character
    jnc semicolon
    ret             ; quit if EOF
semicolon:
    cmp al,';'      ; is it a semicolon?
    jne hash        ; if not, skip to next check
    inc dx          ; increment accumulator
    cmp dl,127      ; if we get to 127, reset it; this saves us the
    je start        ; hassle to perform the modulo when handling #
hash:
    cmp al,'#'      ; is it a hash?
    jne readch      ; if not, skip back to character read
    mov ah,2        ; print dl (it was choosen as accumulator exactly
    int 21h         ; because it's the easiest register to print)
    jmp start       ; reset the accumulator and go on reading
\$\endgroup\$
6
\$\begingroup\$

05AB1E, 25 21 19 bytes

-2 bytes thanks to Adnan

Îvy';Q+y'#Qi127%ç?0

Explanation:

Î                       Initialise stack with 0 and then push input
 v                      For each character
  y';Q+                 If equal to ';', then increment top of stack
       y'#Qi            If equal to '#', then
            127%        Modulo top of stack with 127
                ç       Convert to character
                 ?      Print without newline
                  0     Push a 0 to initialise the stack for the next print

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ I think you can replace i>} by +. \$\endgroup\$ – Adnan May 21 '17 at 19:58
6
\$\begingroup\$

Retina, 34 bytes

T`;#-ÿ`_
\+T`o`-_`[^]|$

Try it online! Includes test case. Edit: Saved 2 bytes with some help from @MartinEnder. Note: Code includes unprintables, and using &#x; codes generates incorrect results as the browser uses Windows-1252 instead of ISO-8859-1. Explanation: The first line cleans up the input: ; is changed to \x80, # to \x7F (due to TIO limitations) and everything else is deleted. Then whenever we see an \x80 that is not before another \x80, we delete it and cyclically increment the code of any next character. This is iterated until there are no more \x80 characters left. Original code that supports null bytes basically subtracts 1 from the unprintable bytes, except in the first line where \xFF is unchanged and \x7F becomes \x00. With escapes for readibility:

T`;#\x00-\xFF`\x7F\x00_
\+T`\x7Eo`\x00-\x7F_`\x7F[^\x7F]|\x7F$
\$\endgroup\$
  • \$\begingroup\$ You can save a byte by combining the last two stages with \x80([^\x80]|$) in the last stage. \$\endgroup\$ – Martin Ender May 23 '17 at 9:19
  • \$\begingroup\$ @MartinEnder Thanks! Annoyingly, \s+T`\x7Fo`\x01-\x80_`\x80(?!\x80).? also only saves one byte. \$\endgroup\$ – Neil May 23 '17 at 9:30
  • \$\begingroup\$ Ah, but [^\x80]|\x80$ saves two bytes, I think. \$\endgroup\$ – Neil May 23 '17 at 9:33
  • \$\begingroup\$ Ah nice, yeah the last one works. I had also tried the negative lookahead, but the s is annoying. \$\endgroup\$ – Martin Ender May 23 '17 at 9:33
6
\$\begingroup\$

R, 97 90 86 84 bytes

A function:

function(s)for(i in utf8ToInt(s)){F=F+(i==59);if(i==35){cat(intToUtf8(F%%127));F=0}}

When R starts, F is defined as FALSE (numeric 0).

Ungolfed:

function (s)
    for (i in utf8ToInt(s)) {
        F = F + (i == 59)
        if (i == 35) {
            cat(intToUtf8(F%%127))
            F = 0
        }
    }
\$\endgroup\$
  • \$\begingroup\$ Shouldn't this be R+pryr? \$\endgroup\$ – L3viathan May 22 '17 at 8:31
  • \$\begingroup\$ @L3viathan Since pryr is an R package, it is still R code. \$\endgroup\$ – Sven Hohenstein May 22 '17 at 8:58
  • \$\begingroup\$ It is R code, but it requires the installation of an additional library. \$\endgroup\$ – L3viathan May 22 '17 at 9:05
  • \$\begingroup\$ @L3viathan Do you think my answer is invalid? Should I avoid using additional packages? \$\endgroup\$ – Sven Hohenstein May 22 '17 at 9:11
  • 2
    \$\begingroup\$ @BLT There is no difference. In my opinion it is no problem to use additional packages that were created before the challenge. This is true for all languages. In Python you have to use import while in R you can use :: to directly access function in packages. You can often see the use of additional packages here (e.g., for Python and Java). However, I changed my former post because I don't want to engage in discussion. \$\endgroup\$ – Sven Hohenstein May 23 '17 at 5:04
5
\$\begingroup\$

Python, 82 bytes

lambda t:''.join(chr(len([g for g in x if g==';'])%127)for x in t.split('#')[:-1])
\$\endgroup\$
  • 1
    \$\begingroup\$ @WheatWizard since you already posted this as an answer, I believe the right action for me would be to upvote it rather than update \$\endgroup\$ – Uriel May 22 '17 at 11:36
4
\$\begingroup\$

Plain TeX, 156 bytes

\newcount\a\def\;{\advance\a by 1\ifnum\a=127\a=0\fi}\def\#{\message{\the\a}\a=0}\catcode`;=13\catcode35=13\let;=\;\let#=\#\loop\read16 to\>\>\iftrue\repeat

Readable

\newcount\a

\def\;{
  \advance\a by 1
  \ifnum \a=127 \a=0 \fi
}
\def\#{
  \message{\the\a}
  \a=0
}

\catcode`;=13
\catcode35=13

\let;=\;
\let#=\#

\loop
  \read16 to \> \>
  \iftrue \repeat
\$\endgroup\$
  • \$\begingroup\$ Can it print characters symbolically? \$\endgroup\$ – eush77 May 21 '17 at 23:20
4
\$\begingroup\$

C (gcc), 58 bytes

a;f(char*s){a+=*s^35?*s==59:-putchar(a%127);a=*s&&f(s+1);}

Try it online! (Hint: click ▼ Footer to collapse it.)

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

Perl, 25 bytes

$_=chr(y%;%%%127)x/#/

Run with perl -043pe (counted as 4 bytes, since perl -e is standard).

Explanation: -043 sets the line-terminator to # (ASCII 043). -p iterates over the input “lines” (actually #-delimited strings, now). y%;%% counts the number of ; in each “line”. x/#/ makes sure that we don’t print an extra character for programs that don’t end in a # (like the third testcase). %127 should be fairly obvious. $_= is the usual boilerplate.

\$\endgroup\$
  • \$\begingroup\$ Impressing one, though there is glitch: for ;;#;;; it outputs #5 instead of #2. \$\endgroup\$ – manatwork May 22 '17 at 15:24
  • \$\begingroup\$ How did you get this result? echo -n ';;#;;;' | perl -043pe '$_=chr(y%;%%%127)x/#/' | xxd correctly outputs 00000000: 02 on my machine. If you left off the 043, or are using a codepage where # is not ASCII 043, that would explain your result. \$\endgroup\$ – Grimmy May 22 '17 at 15:27
  • 1
    \$\begingroup\$ Oops. Sorry, I had a typo in my test. Your code works perfectly. \$\endgroup\$ – manatwork May 22 '17 at 15:32
4
\$\begingroup\$

CJam, 27 bytes

0q{";#"#") 127%co0 "S/=~}%;

Explanation:

0                            e# Push 0
 q                           e# Push the input
  {                          e# For each character in the input:
   ";#"#                     e#   Index of character in ";#", -1 if not found
        ") 127%co0 "S/       e#   Push this string, split on spaces
                      =      e#   Array access (-1 is the last element)
                       ~     e#   Execute as CJam code. ")" increments the accumulator,
                             e#     and "127%co0" preforms modulo by 127, converts to character, pops and outputs, and then pushes 0.
                        }%   e# End for
                          ;  e# Delete the accumulator

Alternative Solution, 18 bytes

q'#/);{';e=127%c}%

Explanation:

q                   e# Read the whole input
 '#/                e# Split on '#'
    );              e# Delete the last element
      {             e# For each element:
       ';e=         e#   Count number of ';' in string
           127%     e#   Modulo by 127
               c    e#   Convert to character code
                }%  e# End for
\$\endgroup\$
  • \$\begingroup\$ Business Cat That doesn't ignore invalid characters. \$\endgroup\$ – Esolanging Fruit May 21 '17 at 19:31
  • \$\begingroup\$ why do you need ; to delete the accumulator? \$\endgroup\$ – caird coinheringaahing May 21 '17 at 19:36
  • \$\begingroup\$ @RandomUser So it doesn't end up getting outputted at the end with the string. \$\endgroup\$ – ETHproductions May 21 '17 at 19:44
4
\$\begingroup\$

F#, 79 91 93 bytes

let rec r a=function|[]->()|';'::t->r(a+1)t|'#'::t->printf"%c"(char(a%127));r 0 t|_::y->r a y

Ungolfed

let rec run acc = function
    | [] -> ()
    | ';'::xs ->
        run (acc + 1) xs
    | '#'::xs ->
        printf "%c" (char(acc % 127))
        run 0 xs
    | x::xs -> run acc xs

Try it online!

Edit: Was treating any other char than ';' as '#'. Changed it so that it's ignoring invalid chars.

Alternative

F#, 107 104 bytes

let r i=
 let a=ref 0
 [for c in i do c|>function|';'->a:=!a+1|'#'->printf"%c"(!a%127|>char);a:=0|_->()]

Use of reference cell saves 3 bytes

Ungolfed

let run i =
    let a = ref 0;
    [for c in i do
        match c with
        | ';' -> a := !a + 1
        | '#' ->
            printf "%c" (char(!a % 127))
            a := 0
        |_->()
    ]

Try it online

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

Processing.js (Khanacademy version), 118 bytes

var n="",a=0;for(var i=0;i<n.length;i++){if(n[i]===";"){a++;}if(n[i]==="#"){println(String.fromCharCode(a%127));a=0;}}

Try it online!

As the version of processing used does not have any input methods input is placed in n.

\$\endgroup\$
  • \$\begingroup\$ You could technically forge your own input method with keyTyped=function(){ ... } :P \$\endgroup\$ – ETHproductions May 21 '17 at 19:18
  • \$\begingroup\$ @ETHproductions This is a look of disgust. \$\endgroup\$ – Christopher May 21 '17 at 19:19
  • \$\begingroup\$ @RandomUser yay! I have done it! I like to answer in Processing (check my answers) \$\endgroup\$ – Christopher May 21 '17 at 19:37
  • 2
    \$\begingroup\$ @RandomUser Not just 1000 rep.. but 2^10 rep ( ͡° ͜ʖ ͡°) \$\endgroup\$ – user47018 May 22 '17 at 17:46
  • \$\begingroup\$ @Midnightas Ohhh yeah \$\endgroup\$ – Christopher May 22 '17 at 18:03
4
\$\begingroup\$

Labyrinth, 61 47 bytes

_36},)@
;    {
; 42_-
"#-  1
_ ; 72
_ ) %
"""".

Try it online!

Explanation

color coded image of the solution code

Code execution begins in the top left corner and the first semicolon discards an implicit zero off the stack and continues to the right.

Orange

  • _36 pushes 36 onto the stack. This is for comparing the input with #
  • } moves the top of the stack to the secondary stack
  • , pushes the integer value of the character on the stack
  • ) increments the stack (if it's the end of the input, this will make the stack 0 and the flow of the program will proceed to the @ and exit)
  • { moves the top of the secondary stack to the top of the primary stack
  • - pop y, pop x, push x - y. This is for comparing the input with # (35 in ascii). If the input was # the code will continue to the purple section (because the top of the stack is 0 the IP continues in the direction it was moving before), otherwise it will continue to the green section.

Purple

  • 127 push 127 to the stack
  • % pop x, pop y, push x%y
  • . pop the top of the stack (the accumulator) and output as a character

From here the gray code takes us to the top left corner of the program with nothing on the stack.

Green

  • _24 push 24 onto the stack
  • - pop x, pop y, push x-y. 24 is the difference between # and ; so this checks if the input was ;. If it was ; the code continues straight towards the ). Otherwise it will turn to the # which pushes the height of the stack (always a positive number, forcing the program to turn right at the next intersection and miss the code which increments the accumulator)
  • ; discard the top of the stack
  • ) increment the top of the stack which is either an implicit zero or it is a previously incremented zero acting as the accumulator for output

From here the gray code takes us to the top left corner of the program with the stack with only the accumulator on it.

Gray

Quotes are no-ops, _ pushes a 0 to the stack, and ; discards the top of the stack. All of this is just code to force the control-flow in the right way and discarding anything extra from the top of the stack.

\$\endgroup\$
  • \$\begingroup\$ Out of curiosity, how did you generate the explanation image? Did you create it yourself? \$\endgroup\$ – Stefnotch Aug 5 '18 at 9:16
  • 2
    \$\begingroup\$ @Stefnotch, I used a text editor to put a tab between each character and then pasted the code into Microsoft Excel which put each character into it's own cell. I selected all cells to give them equal width and height. Then I adjusted colors and borders and took a screenshot. \$\endgroup\$ – Robert Hickman Aug 7 '18 at 16:20
3
\$\begingroup\$

MATL, 29 bytes

';#'&mXz!"@o?T}vn127\c&YD]]vx

Input is a string enclosed in single quotes.

Try it online!

The FizzBuzz program is too long for the online interpreters; see it working offline in this gif:

enter image description here

Explanation

The accumulator value is implemented as the number of elements in the stack. This makes the program slower than if the accumulator value was a single number in the stack, it but saves a few bytes.

';#'       % Push this string
&m         % Input string (implicit). Pushes row vector array of the same size with 
           % entries 1, 2 or 0 for chars equal to ';', '#' or others, respectively
Xz         % Remove zeros. Gives a column vector
!          % Transpose into a row vector
"          % For each entry
  @        %   Push current entry
  o?       %   If odd
    T      %     Push true. This increases the accumulator (number of stack elements)
  }        %   Else
    v      %     Concatenate stack into a column vector
    n      %     Number of elements
    127\   %     Modulo 127
    c      %     Convert to char
    &YD    %     Display immediately without newline
  ]        %   End
]          % End
vx         % Concatenate stack and delete. This avoids implicit display
\$\endgroup\$
3
\$\begingroup\$

Alice, 22 bytes

I!?';-n+?h$'@u%?'#-n$O

Try it online!

Explanation

We keep on the stack only a single counter of how many ; we have encountered. When the stack is empty (e.g. at the start of the program) this is implicitly a 0.

I!?';-n+?h$'@u%?'#-n$O
I                      Push codepoint of next char from input
 !?                    store it on the tape and reload it right away
   ';-n+               add 1 to the counter if this char is a semicolon,
                       0 otherwise
        ?h$'           If the input char was -1 (EOF) execute the next command,
                       otherwise push its codepoint
            @          Terminate the program (or push 64)
             u         Set all bits up to the most significant as equal to 1
                       this turns 64 (1000000b) into 127 (1111111b)
              %        Compute modulo
               ?       reload the input char from the tape
                '#-n$O if it is a hash, pop the counter and print
                       the corresponding character
                       wrap back to the start of the line

A shorter, but non-terminating version of this program can be found here.

\$\endgroup\$
  • \$\begingroup\$ Confirmed it here \$\endgroup\$ – caird coinheringaahing May 22 '17 at 15:00
  • \$\begingroup\$ Sorry for the bad formatting, I've posted this from my phone, I'll fix it as soon as I get my hands on a pc \$\endgroup\$ – Leo May 22 '17 at 15:01
  • \$\begingroup\$ Programs have to terminate unless specified otherwise in the challenge. \$\endgroup\$ – Martin Ender May 23 '17 at 9:08
  • \$\begingroup\$ You can save a byte by using a literal 0x7F instead of ~h though. \$\endgroup\$ – Martin Ender May 23 '17 at 9:11
  • \$\begingroup\$ @MartinEnder made it terminating. I couldn't manage to insert a 0x7F in the code, but I think this alternative modification is more interesting anyway :) \$\endgroup\$ – Leo May 23 '17 at 9:38
3
\$\begingroup\$

JS (ES6), 97 92 bytes

c=>(a=0,y="",c.split``.map(x=>x=="#"?(a%=127,y+=String.fromCharCode(a),a=0):x==";"?a++:0),y)

Tried to take a different approach than Shaggy's answer. Oh well.

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

;#+, 59 bytes, noncompeting

Language was made after this challenge.

;;;;;~+++++++>~;~++++:>*(~<:-+!(<-;->(;))::<+-::!(<#>)-:-*)

Try it online! Input is terminated with a null byte.

Explanation

The generation is the same as from my Generate ;# code answer. The only difference here is is the iteration.

Iteration

*(~<:-+!(<-;->(;))::<+-::!(<#>)-:-*)
*(                                *)   take input while != 0
  ~                                    swap
   <                                   read value from memory (;)
    :                                  move forward to the accumulator memory spot (AMS)
     -                                 flip Δ
      +                                subtract two accumulators into A
       !                               flip A (0 -> 1, else -> 0)
        (     (;))                     if A is nonzero, or, if A == ';'
         <                             read from AMS
          -;-                          increment
             >                         write to AMS
                  ::                   move to cell 0 (#)
                    <                  read value from memory (#)
                     +                 subtract two accumulators into A
                      -                flip Δ
                       ::              move to AMS
                         !(   )        if A == '#'
                           <           read from AMS
                            #          output mod 127, and clear
                             >         write to AMS
                               -:-     move back to initial cell
\$\endgroup\$
3
\$\begingroup\$

Bash + coreutils, 46 39 bytes

tr -dc \;#|sed 'y/;/1/;s/#/.ZC7%P/g'|dc

Try it online!

Explanation

(Thanks Cows Quack for -7 bytes!)

The tr portion removes all extraneous characters (I could put this in the sed for exactly the same bytecount, but then it doesn't handle the linefeed character correctly, since sed leaves them in and dc only gets up to the first linefeed with ?)

sed takes the rest and builds a dc program:

Strings of ; become strings of 1 (a long literal)

# becomes .ZC7%P (if this follows a string of 1, the . is a decimal point for a no-op. But if it's at the beginning of the program, or following another #, it's a literal 0. Then it takes the length of the number, mods it, and Prints the corresponding ASCII.)

\$\endgroup\$
  • \$\begingroup\$ You don't need to escape the ; inside '...' and can simply change dc -ez? to dc. Besides that, instead of ;'s adding 1 to the stack, you can group them together and get their length using Z to reach this tio.run/##S0oszvj/…. \$\endgroup\$ – Kritixi Lithos Sep 8 '18 at 9:10
  • \$\begingroup\$ @Cowsquack That's good, thank you! (and the dc -ez? was a consequence of needing an extra zero to start the program) But your program adds additional output to stderr in either the cases of consecutive # or input that doesn't end with # (in both cases, I mean after extraneous characters are removed). I don't know if there's a consensus, but I feel like the extra output invalidates the solution. I adapted your idea, though, and wound up at just one byte more than your suggestion without dc throwing errors! \$\endgroup\$ – Sophia Lechner Sep 9 '18 at 6:09
  • \$\begingroup\$ According to this stderr can be ignored unless the challenge explicitly states as such, so that is very handy for dc. Also note that this current solution fails with consecutive #s because Z of 0 is 1, so it outputs 0x01 instead of 0x00 (I fell into that same trap as well, but my browser displays unprintables as their hexcodes so I caught that). \$\endgroup\$ – Kritixi Lithos Sep 10 '18 at 9:00
3
\$\begingroup\$

C, 65 64 60 bytes

(-2 thanks to ceilingcat)

c;f(char*s){for(c=0;*s;s++)c+=*s-35?*s==59:-putchar(c%127);}
\$\endgroup\$
  • \$\begingroup\$ You'll need to initialize c to zero to make the function reusable. \$\endgroup\$ – Conor O'Brien May 21 '17 at 23:40
  • \$\begingroup\$ @ConorO'Brien Fixed. Unfortunately I didn't manage to come up with anything shorter than simply adding in the c=0, and I wouldn't want to cheat by copying from Dennis's answer. \$\endgroup\$ – hvd May 22 '17 at 19:41
  • \$\begingroup\$ @ceilingcat Thanks again, I was able to take off three more bytes after that. This does use a trick in Dennis's answer (checked after editing), but this time, so much time had passed that I had forgotten all about it and came up with it on my own. \$\endgroup\$ – hvd Sep 17 '18 at 10:59

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.