# Question
Title: Create a programming language interpreter
**Task:**

You must create an interpreter that can parse snippets of a programming language. The language does not need to be complex, but it must include the following syntactical elements:

* Ability to assign and read variables (could be as simple as `a`-`z` being premade variables)
* If statements (elseif and else are not required)
* Loops (counting to an arbitrary number, user access to counter is not required)
* Simple math with variables (addition, subtraction, multiplication, division, greater/less than, equals)
* Print statements

**Rules:**

* You may not copy the syntax of another popular language.
* You need to write your own interpreter, not modification of another interpreter.
* You can write your interpreter in any language.
* Write a 99-bottles-of-beer example program in your language (see here)
* This is a , so the most upvoted answer wins.

# Answer
> 18 votes
## DogeScript

The 99 bottles of beer program:

```
many amaze 99 time

such scare bottles-of-beer
such scream on-the-wall
many despair 13 time

such fail take-one-down-pass-it-around

wow

so amaze
so scare
so scream
so despair!

so amaze
so scare
so despair!

much amaze

so fail
so despair!

so amaze
so scare
so scream

so despair!
so despair!

very amaze

wow

```

The PHP interpreter:

```
<?php
$input=fopen('php://stdin', 'r');

//pre-process input
$input=preg_replace("/ +/", " ", $input); //replace any multiple spaces by a single space

//split into instructions by newlines
$instructions=explode("\n", $input);

$loopstartpoint= -1;
$variables=array();
$activevariable="";
for($instrpointer=0; $instrpointer<count($instructions); $instrpointer++)
{
    $tokens=explode(" ", $instructions[$instrpointer]);
    switch($tokens[0])
    {
        case "wow":
            if($loopstartpoint<0)
            {
                $loopstartpoint=$instrpointer+1;
            }
            else
            {
                if($variables[ $activevariable ])
                {
                    $instrpointer=$loopstartpoint;
                }
                else
                {
                    $loopstartpoint= -1;
                }
            }
            break;
        case "so":
            if(substr($tokens[1], -1)=="!")
            {
                echo chr($variables[ substr($tokens[1], 0, -1) ]);
            }
            else
            {
                echo $variables[ $tokens[1] ];
                echo " ";
            }
            break;
        case "very":
            $activevariable=$tokens[1];
            break;
        case "much":
            if(!isset($variables[ $tokens[1] ]))
                $variables[ $tokens[1] ]=0;
            if(count($tokens)==2)
            {
                $variables[ $tokens[1] ]--;
            }
            else
            {
                for($loop=0;$loop<$tokens[2];$loop++)
                {
                    $variables[ $tokens[1] ]--;
                }
            }
            $activevariable=$tokens[1];
            break;
        case "many":
            if(!isset($variables[ $tokens[1] ]))
                $variables[ $tokens[1] ]=0;
            if(count($tokens)==2)
            {
                $variables[ $tokens[1] ]++;
            }
            else
            {
                for($loop=0;$loop<$tokens[2];$loop++)
                {
                    $variables[ $tokens[1] ]++;
                }
            }
            $activevariable=$tokens[1];
            break;
        case "such":
            $variables[ $tokens[1] ]=$tokens[2];
            $activevariable=$tokens[1];
            break;
    }
}
?>

```

The syntax as it currently stands:

```
wow - start and end loops, end of loop checks if active variable is 0 and loops if not
so without ! - print variable's value
so with ! - print variable's ASCII character
much - decrement this variable
many - increment this variable
such - set variable
very - make variable active
x time - does previous statement x times

Variables are initially 0.

```

Try it here.
Any suggestions for improvement are welcome.

# Answer
> 10 votes
# BrainBack : A stack based compiled language running on BrainFuck

*NB: Spec was changed from "creating a parser" to "create an interpreter" after i posted this answer. This answer is a compiler which also parses source code.*

The name is a pun on *Back* being the opposite of a well known stack based language and *Brain* indicating it's esoteric nature. It looks a little like BrainFuck (though isn't), but it's compiler runs on BrainFuck and it's compiled object code ends up as BrainFuck binaries.

The language: \*==destroys it's arguments

* `"constant"` prints constant
* `#` prints top of stack as number
* `>` duplicates the top of stack
* `<num>` push constant number `<num>` as a value to top of stack
* `<` remove top of stack
* `-` substract topmost from the second topmost\*
* `+` add topmost to second topmost\*
* `!` not toggles positive / zero\*
* `[ ... ]` does a while top of stack not zero, very similar to BrainFuck

99 bottles of beer with correct lyrics in BrainBack:

```
100
[
 1 -
 > ! [ < 0 0 "No more" ] < [ # 0 ] <
 " bottle"
 > 1 - [ < 0 "s" ] <
 " of beer on the wall, "
 > ! [ < 0 0 "no more" ] < [ # 0 ] <
 " bottle"
 > 1 - [ < 0 "s" ] <
 " of beer.
"
 > ! [ < 0 0 "Go to the store and buy some more, " ] <
     [ "Take one down and pass it around, " 0 ] <

 > ! [ < 1 0 0 "99" ] < [ > 1 - > !  [ < < 1 0 0 "no more" ] < [ # 1 - 0 ] ] <
 " bottle"
 [ < 0 "s" ] <
 " of beer on the wall.

"
]

```

The BrainBack compiler, written in Extended BrainFuck

```
;;; Macros

;; utility function that substracts
;; ^2 from ^0 without reduceing ^2
;; below zero. ^1 needs to be zero
{substract
  (<<[->]>[<]>-)
}

;; Main macro is the main  program and
;; has the overal structure of the program.
;; every macro here is define in order below.
{main
  :i
  :wrk
  :tmp
  :else
  :sub
  $i+(
  ; switch ( $wrk ) cases '"#><-+![]9;' using $tmp,$else
  $tmp+++++(-$wrk------)+$wrk---; !
  ($wrk-; "
    ($wrk-; #
      ($wrk--------; +
        ($wrk--; -
          ($wrk--- $tmp- $else 9+ &substract $tmp+ $wrk; 0-9
            ($wrk--; ;
              ($wrk-; <
                ($wrk--; >
                  ($tmp++++(-$wrk------)+$wrk+; [
                    ($wrk--; ]
                      (#(-) $tmp(-)  no matches)
                        $tmp (- #match 'cl'  &close        )
                    ) $tmp (- #match 'op'    &open         )
                  ) $tmp (- #match 'gt'      &dup          )
                ) $tmp (- #match 'lt'        &slash        )
              ) $tmp (  #match 'c'           &comment      )
            ) $tmp (- #match 0 to 9          &read_number  )
          ) $tmp (- #match 'minus'           &sub          )
        ) $tmp (- #match 'plus'              &add          )
      ) $tmp (- #match '#'                   &print_number )
    ) $tmp (- #match '"'                     &print_string )
  ) $tmp (- #match 'not'                     &not          )

  $i(-)$tmp#,+(-(-$wrk+$i+)))
  10+.
}

;; implements close bracket
{close
    |" close"(-)
    $i.
}

;; implements open bracket
{open
    |" open"(-)
    $i.
}

;; implements dup/>
{dup
    |"dup [->>+<<]>>[-<+<+>>]<
"
     (-)
}

;; implements slash/<
{slash
     |"slash [-]<
"
     (-)
}

;; implements comment
{comment
  [,10-]
}

;; implements read_number/<number>
;; makes code that if run makes
;; the constant
{read_number
  ;TODO: compiler_read_constant_number
   $wrk|"number"(-)
#  $wrk 6+ (- $i 8-)
  ~"+>"<.(-)
  $i+(-(-$wrk.)
     #$else, $tmp 6+ (- $else 8-)
     $else(-$tmp+$i+)
     $sub 9+ &substract
     $else+
     $tmp((-) $i(-) $else-)
     $else(-|"[->++++++++++<]>[-<+>]<"(-)$i+)
     )
   $wrk(-)
   |"
"(-)
}

;; implements sub/-
{sub
     |"sub [-<->]<
"
     (-)
}

;; implements add/+
{add
     |"#add [-<+>]<
"
     (-)
}

;; implements print_number/#
{print_number
  |"print [->+<]>[-<+>>+<]>
    [>++++++++++<
    [->-[>+>>]>[+[-<+>]>+>>]<<<<<]
    +>[-]>[-<<+>>]>[-<<+>>]<<]
    +<[>-<[<]]>[>]
    <[>++++++[-<++++++++>]<-.[-]<]<
"(-)

}

;; implements print_string/"..."
;; this outputs EBF code making the
;; object code EBF
{print_string
  |"print >|"(-)
  $i(-$wrk+$else+)
  $wrk($tmp(-$wrk+)$wrk.,$else(-$tmp+$wrk-$i+)$i(-$else+))
  $tmp(-)$else.(-)|"[-]<
"(-)
}

;; implements not/!
;; creates code that negates top of stack
{not
  |"not >+<[[-]>-]>[<+>->]<<
"(-)
}

&main

```

To compile BrainBack:

```
bf ebf.bf < BrainBack.ebf > BrainBack.bf

```

To compile a BrainBack program:

```
bf BrainBack.bf < 99.bb > 99.ebf # compile from bb to ebf
bf ebf.bf < 99.ebf > 99.bf       # compile from ebf to bf

```

Run the binary:

```
bf 99.bf

```

Here i use bf which is available in most debian distros. `beef` and others can be used as well. Both EBF compiler, BrainBack and its object code becomes quite compatible BrainFuck binaries.

It probably should be extended to print a cell as ascii `.`, be able to read a byte in `,` and to have various `swap` operations to be more useful. It's absolutely needed in order to make a BrainBack compiler or interpreter in BrainBack.

# Answer
> 6 votes
#

I spend most of my time on PHP scripts and it brought me a question: why am I forced to use `$` for my variables names?  is my local currency, so let's use it! Since € is used in many countries, I used some words from EU languages as keywords.

```
€beers gleich 99
€bottles gleich bottles of beer
€bottles_on_the_wall gleich bottles of beer on the wall

mientras €beers topogleich 3
    afficher €beers €bottles_on_the_wall
    afficher , €beers €bottles
    afficher . NETHERLANDS
    odejmowanie €beers

    afficher Take one down and pass it around, €beers
    afficher €bottles_on_the_wall
    afficher . NETHERLANDS NETHERLANDS
sartneim

afficher 2 bottles of beer on the wall, 2 bottles of beer. NETHERLANDS
afficher Take one down and pass it around, 1 bottle of beer on the wall.
afficher NETHERLANDS NETHERLANDS

afficher 1 bottle of beer on the wall, 1 bottle of beer. NETHERLANDS
afficher Take one down and pass it around, no more bottles of beer on the wall.
afficher NETHERLANDS NETHERLANDS

afficher No more bottles of beer on the wall, no more bottles of beer. NETHERLANDS
afficher Go to the store and buy some more, 99 bottles of beer on the wall.
afficher NETHERLANDS NETHERLANDS

```

Keywords:

* `gleich` is *equal* in German
* `mientras` is *while* in Spanish
* `topo` is *greater* in Portuguese (update: it should be *maior* instead, thanks to daHugLenny for the tip)
* `odejmowanie` is *subtract* in Polish
* `afficher` is *print* in French
* newlines are called `nl` sometimes, and the TLD of `NETHERLANDS` is `nl`, so I defined a constant `NETHERLANDS` to display newlines

I cheated a little bit since there is no `if` keyword, I chose to directly print the last two lines.

## Interpreter in Python

The interpreter won't do more than execute the script to display 99 bottles of beers.

```
# -*- coding: utf-8 -*-
# @see http://stackoverflow.com/questions/12655836/writing-an-xml-file-that-contains-a-euro-symbol-in-python-using-xml-etree/12655861#12655861

# =             gleich (german)
# while         mientras (spanish)
# >             topo (portuguese) (it should be "maior" instead)
# subtract      odejmowanie (polish
# print         afficher (french)
# newline       NETHERLANDS

import sys, codecs

class euro:
    symbols = {}
    sign = u'€'

    def executeLine(self, line):
        s = line.split(' ')

        if s[0] == 'afficher':
            buffer = []

            for a in s[1:]:
                if (a == ''):
                    continue
                elif (a[0] == self.sign):
                    buffer.append(str(self.getSymbol(a)))
                elif (a == 'NETHERLANDS'):
                    buffer.append("\n")
                else :
                    buffer.append(a)

            sys.stdout.write(' '.join(buffer))
            # @see http://stackoverflow.com/questions/4499073/printing-without-newline-print-a-prints-a-space-how-to-remove/4499172#4499172
        elif s[0] == 'odejmowanie':
            self.setSymbol(s[1], (int(self.getSymbol(s[1])) - 1))
        elif (len(s) >= 3) and (s[1] == 'gleich'):
            self.setSymbol(s[0], (' ').join(s[2:]))

    def executeBlock(self, lines, statement):
        while (self.getStatement(statement)):
            for line in lines:
                self.executeLine(line)

    def getStatement(self, statement):
        if (statement[1] == 'topogleich'):
            return self.getSymbol(statement[0]) >= int(statement[2])

    def setSymbol(self, name, value):
        name = self.withoutEuro(name)
        self.symbols[name] = value

    def getSymbol(self, name):
        #~ print symbols, withoutEuro(name)
        name = self.withoutEuro(name)
        if name in self.symbols:
            value = self.symbols[name]

            return value
        else :
            print "\n-----\n",'Error: "', name, '"is not in', self.symbols, '-----'

            #~ sys.exit()

    def withoutEuro(self, string):
        return(string.replace(self.sign, ''))

    def parseFile(self, f):
        linesStack = []

        for line in codecs.open(f, 'r', 'utf-8'):
            line = line.replace('\n', '').replace('\t', '')
            s = line.split(' ')

            if (len(s) == 1) & (s[0] == '') :
                continue

            if (s[0] == 'mientras'):
                statement = s[1:]

                linesStack.append(line)
            elif (s[0] == 'sartneim'):
                linesStack.append(line)

                self.executeBlock(linesStack, statement)

                linesStack = []
                statement = ''
            elif (len(linesStack) > 0):
                linesStack.append(line)
            else:
                self.executeLine(line)

euro = euro()
euro.parseFile(sys.argv[1])

```

To run it, save both files then run the Python file with the `.eu` script as an argument:

```
python euro.py euro.eu

```

# Answer
> 5 votes
# 1Lang

1Lang is a functional prefix language like LISP or Scheme but without parentheses that makes it a bit harder to read when all unnecessary white-space is removed. Parentheses can be removed since all functions and operators take a known number of parameters.

Braces are required to delimit function body and conditional consequence and alternate code blocks which can consist of a list of statements.

In LISP, Factorial might be defined like this:

```
(defun fact (x) (if (< x 2) 1 (* x (fact (- x 1))) ) )

```

in 1Lang this would be

```
@Fx{ ? < x 2 {1} {* x F -x1} }

```

which can be reduced to

```
@Fx{?<x2{1}{*xF-x1}}

```

1Lang currently supports no side-effects.

1Lang is written in bash so it currently shares some bash limitations such as integer range.

```
a-z are variables. Variable are either integers, strings, or lists.

```

NB: Lists are not fully implemented.

```
A-Z are functions

```

Integers are bash integers (up to -2^32 to 2^31-1 I think). Negative numbers can not be directly used. To enter a negative, subtract it from zero. eg. -5 would be entered as -0 5. This limitation is because 1Lang is a work in progress and negative numbers were not needed for this application. I am considering using ~ as a unary negative operator which would allow -5 to be input as ~5.

White-space is required to delineate integers. eg. +2 3

```
: means assign                                    eg. :c34 to assign 34 to c
+-*/% are binary integer operators                eg. +12 34
&|^ are binary bit-wise operators
! is unary boolean not
~ is unary one's complement
? is a if-then-else function-like operator.       eg. ?=x3{*xx}{0} is x=3 return x*x else 0
+ is also a binary string concatenation operator  eg. +99" bottles"
* is also a string repetition operator            eg. *5" hello" or *" hello"5
@ defines a function                              eg. @Fx{?<x1{1}{*xF-x1}}

```

Function parameter names may overload callers variables. All variables assigned within a function are local.

Printing is not necessary (although it could be useful) because like LISP every statement returns a value, and last value returned is printed.

```
eg. +2 3 prints 5

```

An unexpected behaviour of prefix notation without parentheses is that string concatenation can actually be easy to write. Say you want to concatenate `"a" " quick" " brown" " fox"`, one might write:

```
+++"a"" quick"" brown"" fox"

```

But a more readable and less error prone method is this:

```
+"a"+" quick"+" brown"" fox" (Note missing + between last terms)

```

or

```
+"a"+" quick"+" brown"+" fox"""

```

99 Bottles of beer code:

```
:b" of beer"
:w" on the wall"
:t"Take one down and pass it around, "
:s"Go to the store and buy some more, "
:c", "
:n".\n"
@Bx{?=x0{+"No more bottles"b}{+x+" bottle"+?=x1{""}{"s"}b}}
@Fx{?=x0{+B0+w+c+B0+n+s+B99+wn}{+Bx+w+c+Bx+n+t+B-x1+w+n+"\n"F-x1}}
F99

```

Function B returns "No more bottles" or "1 bottle" or " bottles" depending on x.

Function F returns normal verses or final verse. A normal verse is concatenated with following verse by recursively calling F with -x1. When x is 0, F returns final verse.

This generates (for F5 meaning start at 5 bottles of beer...):

```
> F5
5 bottles of beer on the wall, 5 bottles of beer.
Take one down and pass it around, 4 bottles of beer on the wall.

4 bottles of beer on the wall, 4 bottles of beer.
Take one down and pass it around, 3 bottles of beer on the wall.

3 bottles of beer on the wall, 3 bottles of beer.
Take one down and pass it around, 2 bottles of beer on the wall.

2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottle of beer on the wall.

1 bottle of beer on the wall, 1 bottle of beer.
Take one down and pass it around, No more bottles of beer on the wall.

No more bottles of beer on the wall, No more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.
<End>

```

## 1Lang interpreter (written in bash) in under 500 lines.

```
#!/bin/bash

LC_ALL=C  # else [a-z] and [A-Z] misbehave

# functions return result on stdout
# functions have an environment

# Requirements:
# * minimise size
#   -> eliminate delimiters
#   -> single letter variables and functions
#   -> no precidence
#   -> no overloading
# *

# string "text with \characters as per printf"
# numbers 123
# functions F3
# Built-ins +-*/%^ &|~ ! etc.
# assignment :v12 :v"string"

log(){  local m="${l:p}" m="${m//[$NL]/\n}" v="${FUNCNAME[1]}"; echo "$v: l=[${l//[$NL]/\n}] ch=[${ch/[$NL]/\n}] next=[$m]" >&2; }
logr(){ local m="${l:p}" m="${m//[$NL]/\n}" v="${FUNCNAME[1]}"; echo "$v: l=[${l//[$NL]/\n}] ch=[${ch/[$NL]/\n}] next=[$m] ret=[${ret//[$NL]/\n}]" >&2; }
logv(){ local        v="${FUNCNAME[1]}"; echo "$v: ret=[${ret//[$NL]/\n}]" >&2; }
logm(){ local m="$1" v="${FUNCNAME[1]}"; echo "$v: ${m//[$NL]/\n} in [${read//[$NL]/\n}]." >&2; }

msg(){ echo -En "$1" >&2; }
msn(){ echo -E  "$1" >&2; }

# ==========
# Line layer
# ==========

declare l
readline(){ read -rp"1lang> " l; }

#==================
# Environment Layer
#==================

declare -A v t  # variables and variable type
declare ret typ  # all bash function return these values

# assign = : var expression
assign(){
  local var
  readch
  var && var=$ret || { logm "ERROR: variable name expected"      ; return 1; }
  exp             || { logm "ERROR: value or expression expected"; return 1; }
  v["$var"]="$ret"
  t["$var"]="$typ"
}

# get variable value
get(){
  local var
  var && var=$ret || { logm "ERROR: variable name expected"; return 1; }
  ret=${v["$var"]}
  typ=${t["$var"]}
}

declare -A func fpar
declare -iA fnum                 # functions
# define = @ F param* { body }
define(){
  local fn par body
  readch
  fn && fn=$ret || { logm "ERROR: function name expected"; return 1; }
  fpar[$fn]=                     # zero parameters
  fnum[$fn]=                     # zero parameter counter
  while var;do                   # read parameters
    fpar[$fn]+=$ret
    fnum[$fn]+=1                 # cound parameters
  done
  # get body but remove block delimiters
  skip "{" "}" && body="${ret:1: -1}" || { logm "ERROR: function body expected"; return 1; }
  readch                         # skip }
  func[$fn]="$body"              # store function body
  ret="@$fn${fpar[$fn]}{$body}"
  typ='f'
}

apply(){
  local fn=$ch n c s; local -i N q
  readch
  N=${fnum[$fn]}   # number of parameters
  n=${fpar[$fn]}   # parameters
  s=${func[$fn]}   # function body
  c=
  for((q=0; q<N; q++)){
    exp || { logm "ERROR: value expected"; return 1; }
    c+="v[${n:q:1}]=\"$ret\"; "  # add value to script
    c+="t[${n:q:1}]=\"$typ\"; "  # add type to script
  }
  # parse function in a subshell and echo result and type back
  # subshell means all variable changes in function are local
  c+="parse <<<'$s'; echo -E \"\$typ\$ret\""  # combine type and value
  ret=
  typ=
  ret="$( eval "$c" )" || { logm "ERROR: function application failed"; return 1; }
  typ="${ret::1}"  # extract type
  ret="${ret:1}"   # get actual return value
}

# bash oddities:

# [[ 1 -eq 1 ]] -> 0 or success
# [[ 1 -eq 2 ]] -> 1 or failed

# x=1\<2 -> a=1 (true)
# x=1\<1 -> a=0 (false)

# ((1==1)) -> 0 or success
# ((1==2)) -> 1 or failed

# declare -i a; a=1==1 -> a=1 (true)
# declare -i a; a=1==2 -> a=0  (false)

binary(){
  local -i iret; local op=$ch a b at bt
  readch
  exp && { a="$ret"; at=$typ; } || { logm "ERROR: initial expression expected"; return 1; }
  exp && { b="$ret"; bt=$typ; } || { logm "ERROR: second expression expected"  ; return 1; }
  ret=
  typ=
  case "$at$bt" in
    nn)  # num op num
      case "$op" in
        [\*]) iret=a*b;;
        [\^]) iret=a**b;;
        [\+]) iret=a+b;;
        [\-]) iret=a-b;;
        [\/]) [[ b -ne 0 ]] && { iret=a/b; } || { logm "ERROR: division by 0"       ; return 1; };;
        [\%]) [[ b -ne 0 ]] && { iret=a%b; } || { logm "ERROR: modulo division by 0"; return 1; };;
        [\&]) iret=a\&b;;
        [\|]) iret=a\|b;;
        [\#]) iret=a\^b;;
        [\=]) iret=a==b;;
        [\<]) iret=a\<b;;
        [\>]) iret=a\>b;;
      esac
      ret=$iret
      typ='n';;  # result is always a decimal number
    ss)  # string op string
      case "$op" in
#        [\*]) arith=a*b;;  # combine?
#        [\#]) arith=${}a**b; type='s';;
        [\+]) ret="$a$b"; typ='s';;  # concatenate
        [\-]) ret="${a//$b}"; typ='s';;  # remove substrings
        [\=]) [[ $a = $b ]]; ret=$?; typ='n';;
        [\<]) [[ $a < $b ]]; ret=$?; typ='n';;
        [\>]) [[ $a > $b ]]; ret=$?; typ='n';;
      esac;;
    ns)  # num op string  =3"hello"  ="hello"3  ="3"3  =3"4"
      case "$op" in
        [\+]) ret="$a$b"; typ='s';;  # concatenate
        [\*]) ret=$(eval echo \"\${b[0]\"{1..$a}\"}\"); typ='s';;  # repeat b a times
        [\=]) ((${#b}==a)); ret=$?; typ='n';;  # length b is a
#        [\<]) [[ $a < $b ]]; arith=$?; typ='n';;
#        [\>]) [[ $a > $b ]]; arith=$?; typ='n';;
      esac;;
    sn)  # string op num  *"hello"3  ="3"3  =3"4"
      case "$op" in
        [\+]) ret="$a$b"; typ='s';;  # concatenate
        [\*]) ret=$(eval echo \"\${a[0]\"{1..$b}\"}\"); typ='s';;  # repeat a b times
        [\=]) ((${#a}==b)); ret=$?; typ='n';;  # length a is b
#        [\<]) [[ $a < $b ]]; arith=$?; typ='n';;
#        [\>]) [[ $a > $b ]]; arith=$?; typ='n';;
      esac;;
    *) logm "ERROR: undefined operation [$op] for [$a] [$at] and [$b] [$bt]"; return 1;
  esac
  return 0
}

# FIXME: string ops?
unary(){
  local -i iret; local op="$ch"
  readch
  exp || { logm "ERROR: expression expected"; return 1; }
  case "$op" in
    [\!]) iret=\!ret;;
    [\~]) iret=\~ret;;
  esac
  ret=$iret
  typ='n'  # result is always a decimal number
}

#==============
# Control Layer
#==============

# iff = ? boolean { consequence block } { alternative block }
# ?<1 2{+4 5}{+1 2}
iff(){
  local -i c; local iff ift
  readch
  exp && c=$ret || { logm "ERROR: value or expression expected"; return 1; }
  [[ c -eq 1 ]] && {  # true so do consequence
    ws
    block && { iff="$ret"; ift="$typ"; } || { logm "ERROR: consequence block error"; return 1; }
    ws
    skip "{" "}" || { logm "ERROR: alternate block expected"; return 1; }
    ret="$iff"
    typ="$ift"
  } || {
    ws
    skip "{" "}" || { logm "ERROR: consequence block expected"; return 1; }
    ws
    block || { logm "ERROR: alternate block error"; return 1; }
  }
}

#==============
# Symbols Layer
#==============

# fn = [A-Z]
fn(){
# FIXME: make evalu?
  [[ $ch = [A-Z] ]] || return 1
  ret=$ch
  typ='c'
  readch
}

# var = [a-z]
var(){
# FIXME: make evalu?
  [[ $ch = [a-z] ]] || return 1
  ret=$ch
  typ='c'
  readch
}

# list = ( token* )
# FIXME: not finished and no operators support lists
list(){
  local list=$ch prev
  readch
  while [[ $ch != ')' ]];do
    exp || { logm "ERROR: expression expected"; return 1; }
    case $typ in
      [n]) list+=" $ret";;
      [s]) list+="$ret";;
      [l]) list+="$ret";;
    esac
    ws
  done
  ret="$list$ch"
  readch
  typ='l'
  return 0
}

#============
# Token Layer
#============

# char = ' echoch
#echoch = \ {special echo escape character} | {char}
char(){
  readch
  case "$ch" in
    [\\]) escch || { logm "ERROR: escape character expected"; return 1; };;
       ?) ret="$ch"; readch
  esac
  typ='c'
}

# escaped characters are a pain
# use read with -r to read in verbatim - no escaping
# use echo -E to write out verbatim (except \\ may be processed)

declare escchS
declare ECHO='abefnrtv'
# double \\ for a \
escch(){
  local ESC="$ch"
  readch    # skip \
  case "$ch" in
    [$ECHO])                   printf -v ret "%b" "$ESC$ch"; readch;;
       [\\]) ret="\\"; readch;;
       [\"]) ret="\""; readch;;
      [0-7])         onum && { printf -v ret "%b" "$ESC$ret"   ; } || { logm "ERROR: octal number expected"; return 1; };;
       [xU]) readch; hnum && { printf -v ret "%b" "${ESC}x$ret"; } || { logm "ERROR: hex number expected"  ; return 1; };;
          ?) ret="$ch"
             [[ $escchS ]] || {
               tidyReadCh
               logm "WARNING: only octal, hex, unicode, and [$ECHO\\\"] characters need to be escaped with '$ESC'"
               logm "WARNING: [$ch] in [$l] does not need to be escaped"
               escchS="OFF"
             }
             readch
  esac
  typ='c'
}

#  num =  digit  digit*
# onum = odigit odigit*
# onum = hdigit hdigit*

num(){  local num; num=$ch; readch; while  digit;do num+=$ret; done; ret=$num; typ='n'; }
onum(){ local num; num=$ch; readch; while odigit;do num+=$ret; done; ret=$num; typ='n'; }
hnum(){ local num; num=$ch; readch; while hdigit;do num+=$ret; done; ret=$num; typ='n'; }

#  digit = [0-9]
# odigit = [0-7]
# odigit = [0-9a-fA-F]
digit(){  [[ $ch == [0-9]       ]] || { ret=-1; return 1; }; ret=$ch; typ='s'; readch; }
odigit(){ [[ $ch == [0-7]       ]] || { ret=-1; return 1; }; ret=$ch; typ='s'; readch; }
hdigit(){ [[ $ch == [0-9a-fA-F] ]] || { ret=-1; return 1; }; ret=$ch; typ='s'; readch; }

# string = " char* "
# char = escch | {any character}
string(){
  skip "\"" "\"" || { logm "ERROR: quoted string expected"; return 1; }
  ret="${ret:1: -1}"
  typ='s'
  return 0
}

# ==========
# Char layer
# ==========

declare ch read
declare -i p L COUNT
readch(){
  if [[ p -eq L ]]; then  # need more code
    readline || { ch=; p=L=0; l="EOF"; return 1; }
    l+=$NL;
    p=0
    L=${#l}
  fi
# FIXME: remove once eady - prevents bash consuming all memory
  COUNT+=1
  ((COUNT>100000)) && { logm "FAILSAFE: too many charcters read"; return 1; }
  ch="${l:p:1}"
  read+="$ch"
  p+=1  # queue next character
}

# skip = SS content* ES
# content = ch | escch | skip(SS ES)
# string = " ch* "
skip(){
  local s="$1" e="$2" b="$ch"
  typ='z'                    # code fragment
  [[ $ch != $s ]] && return  # nothing to skip
  readch
  while [[ -n $ch ]];do
    case "$ch" in
        $e)                 b+="$e"  ; readch; ret="$b"; return 0;;
        $s) skip "$s" "$e"; b+="$ret";;
      [\\]) escch         ; b+="$ret";;
      [\"]) skip "\"" "\""; b+="$ret";;
         ?)                 b+="$ch" ; readch
    esac
  done
  ret="$b"
  logm "ERROR: unexpected EOF"
  exit 1
}

# FIXME: still required?
shopt -s extglob
shopt -u nocasematch

declare NL; printf -v NL "%b" "\n"                 # echo $NL | hexdump -C
declare WS; printf -v WS "%b" " \n\t\r"            # define whitespace

# FIXME: should it set ret and typ?
ws(){ while [[ $ch == [$WS] ]];do readch; done; }  # skip any WS

#=====
# eval
#=====

# exp = [0-9] num
#       | " string "
#       | : assignment
#       | @ function definition
#       | [-+*/%^] binary operation
#       | [&|#<>=] boolean operation
#       | [!~] unary operation
#       | [A-Z] function application
#       | [a-z] variable
#       | ? if expression
#       | { expression* } block expression
#       | ( expression* ) list of expressions

# spare prefix characters [ '$[]_\;, ]
# [v  head of list
# ]v tail of list

exp(){
  ws
  case "$ch" in
              [0-9]) num    || { logm "ERROR: number expected"               ; return 1; };;
#               [\']) char   || { logm "ERROR: char expected"                 ; return 1; };;
               [\"]) string || { logm "ERROR: string expected"               ; return 1; };;
               [\:]) assign || { logm "ERROR: assignment expected"           ; return 1; };;
               [\@]) define || { logm "ERROR: function definition expected"  ; return 1; };;
           [-+*/%^]) binary || { logm "ERROR: binary expression expected"    ; return 1; };;
       [\&\|#\<\>=]) binary || { logm "ERROR: binary expression expected"    ; return 1; };;
              [\!~]) unary  || { logm "ERROR: unary expression expected"     ; return 1; };;
              [A-Z]) apply  || { logm "ERROR: function failed"               ; return 1; };;
              [a-z]) get    || { logm "ERROR: variable name expected"        ; return 1; };;
               [\?]) iff    || { logm "ERROR: boolean expression expected"   ; return 1; };;
               [\{]) block  || { logm "ERROR: code block expected"           ; return 1; };;
               [\(]) list   || { logm "ERROR: list expected"                 ; return 1; };;
                 '') ret=;       logm "ERROR: unexpected EOF"                ; return 1;;
                  *) ret="$ch"                                               ; return 1;;
  esac
  return 0
}

# block = { code }
block(){
  readch                         # skip {
  while [[ $ch != "}" ]];do
    exp || {
      tidyReadCh
      logm "WARNING: ignoring previous error or unknown symbol [$ch]"
      [[ errors+=1 -gt 5 ]] && { logm "ERROR: exiting due to too many warnings"; exit 1; }
    }
    ws
  done
  readch    # skip }
  return 0
}

#=====
# repl
#=====

# pass an expression on stdin- not used withing same ebvironment - called by apply
parse(){
  p=L  # force readline
  ch=
  read=
  readch  # clears ch
  while [[ $ch && $ch != '.' ]];do
    exp || { logm "ERROR: expression expected"; return 1; }
    read=$ch
    ws
  done
# last expression is returned as result
}

tidyReadCh(){
  tidyRead
  ch="${ch//[$NL]/\n}"
}
tidyRead(){
  read="${read//[$NL]}"
}

# repl = eval* EOF
# eval = evalu | readch
repl(){
  readch
  while [[ $ch && $ch != '.' ]];do
    exp && {
      tidyRead
      msn "> $read"  # echo line except for WS
#      echo -E "$ret [$typ]"
      echo -E "$ret"
      read=$ch
    } || {
      tidyReadCh
      msn "> $read"
      logm "WARNING: ignoring previous error or unknown symbol [$ch]"
      read=
      readch
      [[ errors+=1 -gt 5 ]] && { logm "ERROR: exiting due to too many warnings"; exit 1; }
    }
    ws
  done
  msn "<End>"
}

#=====
# test
#=====
# FIXME: negative numbers

msn "1Lang"

repl <<<'
:b" of beer"
:w" on the wall"
:t"Take one down and pass it around, "
:s"Go to the store and buy some more, "
:c", "
:n".\n"
@Bx{?=x0{+"No more bottles"b}{+x+" bottle"+?=x1{""}{"s"}b}}
@Fx{?=x0{+B0+w+c+B0+n+s+B99+wn}{+Bx+w+c+Bx+n+t+B-x1+w+n+"\n"F-x1}}
F99
'

```

# Answer
> 4 votes
# Half (interpreter/translator in Windows Batch)

I don't know why I'm answering so many puzzles in windows batch, for some sick reason I think I'm enjoying it :P Anyways, this is similar to something I worked on for fun a while ago, a basic language that's translated to windows batch by a script that is also written in windows batch. It's not particularly amazing, but it works.

## 99 Bottles of Beer

```
# Initialize variables
bottles ~ 99
# You can't directly compare a literal value
zero ~ 0

# This makes a point 'loop' that can be jumped to or used as a subroutine
mark loop
    write $ bottles
# You only need quotes when you have leading or trailing spaces
    print ~ " bottles of beer on the wall,"
    write $ bottles
    print ~ " bottles of beer."
    print ~ Take one down and pass it around,
    bottles @ bottles-1
    if
    bottles equ zero
        jump none
    endif
    write $ bottles
    print ~ " bottles of beer on the wall."
    print ~
jump loop

mark none
    print ~ no more bottles of beer on the wall.
    print ~
    print ~ No more bottles of beer on the wall,
    print ~ No more bottles of beer.
    print ~ Go to the store and buy some more,
    print ~ 99 bottles of beer on the wall.

```

## Syntax

Only three tokens are recognized on each line, separated by spaces.

\# is a comment.

In most cases where a value is needed, a `$` in the second token signifies that the third should be treated as a variable name, whereas a `~` denotes a literal value. General instructions take the form `<instruction> [$~] <name>`. Setting a variable takes the same form, but is implemented whenever is not recognized.

Defined commands:

* `print` and `write` both write output, but `write` does not add a newline. Needs $ or ~.
* `mark` creates a point that can be jumped to or called as a subroutine.
* `jump` equivalent of goto in batch (or any language for that matter).
* `proc` calls a subroutine. Equivalent of `call :label`.
* `return` returns from a subroutine. Will exit the program when not inside one.
* `if` conditional instruction. Takes comparison from the next line, in the form `<var1> <operator> <var2>`. Operators are the same as `if`'s in batch, ie. `EQU, NEQ, LSS, LEQ, GTR, GEQ`. Will execute instructions after it only if the comparison is true.
* `endif` ends an if statement.
* `cat` concatenates two variables. `cat a b` will store the value of ab in a.

When none of these commands are found, the expression is treated as a variable assignment, using the first token as the variable name. `$` and `~` behave the same as in `print`, but there is also a `@` identifier. This treats the last token as a mathematical expression, passed to `set /a`. It includes most operators. If none of the three identifiers are found, this is a syntax error and the interpreter exits.

## Interpreter (Windows Batch)

The interpreter actually translates the code into windows batch, places it in a temporary file and executes it. While it recognizes syntax errors in the Half language, the resulting batch script may cause issues, especially with special characters like parentheses, vertical bars etc.

```
@echo off

REM Half Interpreter / Translator

if exist ~~.bat del ~~.bat
if not exist "%1" call :error "File not found: '%1'"
set error=
setlocal enabledelayedexpansion
call :parse "%1" 1>~~.bat
if exist ~~.bat if not "error"=="" ~~.bat 2>nul
goto :eof

:parse
set ifstate=0
echo @echo off
echo setlocal
echo setlocal enabledelayedexpansion
for /f "eol=# tokens=1,2* delims= " %%a in (%~1) do  (
    if "!ifstate!"=="1" (
        if /i not "%%b"=="equ" if /i not "%%b"=="neq" if /i not "%%b"=="lss" if /i not "%%b"=="leq" if /i not "%%b"=="gtr" if /i not "%%b"=="geq" call :error "Unknown comparator: '%%b'"
        echo if "^!%%a^!" %%b "^!%%c^!" ^(
        set ifstate=0
    ) else (
        if "%%a"=="print" (
            if "%%b"=="$" (
                echo echo.^^!%%c^^!
            ) else if "%%b"=="~" (
                echo echo.%%~c
            ) else call :error "Unknown identifier for print: '%%b'"
        ) else if "%%a"=="write" (
            if "%%b"=="$" (
                echo echo^|set/p="^!%%c^!"
            ) else if "%%b"=="~" (
                echo echo^|set/p="%%~c"
            ) else call :error "Unknown identifier for write: '%%b'"
        ) else if "%%a"=="mark" (
            if not "%%c"=="" call :error "Unexpected token: %%c"
            echo :%%b
        ) else if "%%a"=="jump" (
            if not "%%c"=="" call :error "Unexpected token: %%c"
            echo goto :%%b
        ) else if "%%a"=="proc" (
            if not "%%c"=="" call :error "Unexpected token: %%c"
            echo call :%%b
        ) else if "%%a"=="return" (
            if not "%%c"=="" call :error "Unexpected tokens: %%b %%c"
            if not "%%b"=="" call :error "Unexpected token: %%b"
            echo goto :eof
        ) else if "%%a"=="if" (
            if not "%%c"=="" call :error "Unexpected tokens: %%b %%c"
            if not "%%b"=="" call :error "Unexpected token: %%b"
            set ifstate=1
        ) else if "%%a"=="endif" (
            if not "%%c"=="" call :error "Unexpected tokens: %%b %%c"
            if not "%%b"=="" call :error "Unexpected token: %%b"
            echo ^)
        ) else if "%%a"=="cat" (
            echo set "%%b=^!%%b^!^!%%c^!"
        ) else (
            if "%%b"=="$" (
                echo set "%%a=!%%c!"
            ) else if "%%b"=="~" (
                echo set "%%a=%%~c"
            ) else if "%%b"=="@" (
                echo set/a"%%a=%%c"
            ) else call :error "Unknown tokens '%%a %%b %%c'"
        )
    )
)
echo endlocal
goto :eof

:error
echo.Parse Error: %~1 1>&2
set error=1
goto :eof

```

# Answer
> 4 votes
# Flex Bison

Assign variable, if else condition block and some other addition, subtraction operation.

Laxical file `lex.l`

```
%{
 #include <stdio.h>
 #include <stdlib.h>
%}

 var [A-Za-z][A-Za-z0-9]*
 digit [0-9]+
 comment \*\*[A-Za-z0-9\*\/\+\-\(\)\"\' \t;:=]*\n

 %%
 print {return(PRINT);}
 save {return(SAVE);}
 {digit} {yylval=atoi(yytext);return(DIGIT);}
 {var} {yylval=strdup(yytext);return(VAR);}
 \* {return(M_SIGN);}
 \/ {return(D_SIGN);}
 \+ {return(A_SIGN);}
 \- {return(S_SIGN);}
 \( {return(L_BRACE);}
 \) {return(R_BRACE);}
 = {return(E_SIGN);}
 ; {return(S_COLON);}
 : {return(COMMA);}
 \n {return (NW_LINE);}
 [ \t] /*skip*/;
 {comment} /*skip*/;
 %%

```

Parser file `com.y`

```
  %{
    #include <ctype.h>
    #include <stdio.h>
    FILE *save_p;
    int new_line=1,stack_top=0,trigger=1;
    void value_store(int);
    int check_srore(char name_var[],int);
    void error(int);

    struct store
    {
     int var_value;
     char var_name[10];
     }info[10];

    %}

      %token PRINT SAVE S_COLON L_BRACE R_BRACE DIGIT VAR COMMA NW_LINE
      %left A_SIGN S_SIGN
      %left D_SIGN M_SIGN
      %right E_SIGN

      %%
      commands :
         | commands command
          ;
      command : expers
        | print
        | save
        | NW_LINE{new_line++;}
          ;

           save : SAVE expr etest {fprintf(save_p,"%d\n",$2);}
            ;

           expers  : store_val equal expr etest{value_store($3);}
        ;

           print    : PRINT expr etest {printf("%d\n",$2);}
              ;

           etest    : S_COLON
        | DIGIT {error(0);}|PRINT{error(0);}|SAVE{error(0);}
         | VAR{error(0);}|COMMA{error(0);}
         ;

           store_val : VAR {check_store($1,0);}
          ;

           expr    : expr A_SIGN expr      { $$ = $1 + $3; }
                | expr S_SIGN expr      { $$ = $1 - $3; }
                | expr M_SIGN expr      { $$ = $1 * $3; }
                    | expr D_SIGN expr      { $$ = $1 / $3; }
                | L_BRACE expr R_BRACE  { $$ = $2; }
                | DIGIT
                | retriv_var
                ;

             equal   : E_SIGN
             ;

             retriv_var : VAR { $$=check_store($1,1); }
           ;

        %%

        #include "lex.yy.c"

        void error(int temp)
         {
                char *err[]={
                     "Statement Missing\n",
                 "Compund Statement Missing\n",
                     "Variable need a value\n",
                     "Invalid Argument\n"
          };
             printf("In line no.%d:\t%s",new_line,err[temp]);
         exit(1);
        }

      void value_store(int store_val)
      {
       stack_top--;
      info[stack_top++].var_value = store_val;
      }

   int check_store(char name_var[],int status)
   {
     int temp = 0;
   do{
    if(strcmp(info[temp].var_name,name_var)==0)
    {
   trigger=0;
       if(status)
   {
          trigger=1;
      return (info[temp].var_value);
   }
     }
    temp++;
   } while(temp<stack_top);

    if(trigger)
    {
if(status)
{
  trigger=1;
      error(2);
}
    else
strcpy(info[stack_top++].var_name,name_var);
   }
      else trigger=1;

  }

  int yyerror(const char *str)
  {
    fprintf(stderr,"error: %s\n",str);
  }

  main(int argc, char *argv[])
  {

if(argc != 3)
{
     error(3);
}
   yyin = fopen(argv[1],"r");
   save_p = fopen(argv[2],"w");
   yyparse();
   fclose(yyin);
   fclose(yyout);
  }

```

Compile

1. List item
2. flex lex.l
3. bison com.y
4. gcc -o compiler com.tab.c -lfl

Run

compiler in.txt ou.txt

Input file

a = 3 + (4 \*7) -9; print a; c = a+45; print c;

\**This is comment save c;

\** save c in the file print c\*(a+32);

Output file 67

# Answer
> 3 votes
I give you:

# Small Instruction Set Interpreter (SISI)

The syntax draws on BASIC and assembly. It has four statements: `set`, `print`, `jump` (unconditional goto), and `jumpif` (conditional goto). Every statement must be preceded by a line number. Supported data types are integers and strings.

The interpreter itself can be found in Python 3 on Github (sisi.py). The 99 Bottles of Beer program is there as well, but I'll reproduce it here:

```
10 set x 99
20 set bottles " bottles "

100 set line x + bottles
110 set line line + "of beer on the wall, "
120 set line line + x
130 set line line + bottles
135 set line line + "of beer."
140 print line

200 set x x - 1
210 set none x = 0
220 jumpif none 400
230 set multiple x > 1
240 jumpif multiple 300
250 set bottles " bottle "

300 set line "Take one down and pass it around, " + x
310 set line line + bottles
320 set line line + "of beer on the wall."
330 print line
340 print ""
350 jump 100

400 print "Take one down and pass it around, no more bottles of beer on the wall."
410 print ""
420 print "No more bottles of beer on the wall, no more bottles of beer."
430 print "Go to the store and buy some more, 99 bottles of beer on the wall."

```

# Answer
> 2 votes
# Interpreter

For instructions on how to run this code, take a look at my other answer: https://codegolf.stackexchange.com/a/19935/13186

# 99 Bottles of Beer

## The Program

```
 bottles of beer on the wall, @ bottles of beer.
Take one down and pass it around, @ bottles of beer on the wall.

@ bottle of beer on the wall.

1 bottle of beer on the wall, 1 bottle of beer.
Take one down and pass it around, no more bottles of beer on the wall.
@@@@@@@@@@@@@@

#9.{
    !#48.+

    !<#57.<#0.^<!<#57.<#1.^<!<#56.<#64.^<
    !<#56.<#0.^<!<#56.<#1.^<!<#55.<#64.^<
    !<#55.<#0.^<!<#55.<#1.^<!<#54.<#64.^<
    !<#54.<#0.^<!<#54.<#1.^<!<#53.<#64.^<
    !<#53.<#0.^<!<#53.<#1.^<!<#52.<#64.^<
    !<#52.<#0.^<!<#52.<#1.^<!<#51.<#64.^<
    !<#51.<#0.^<!<#51.<#1.^<!<#50.<#64.^<
    !<#50.<#0.^<!<#50.<#1.^<!<#49.<#64.^<
    !<#49.<#0.^<!<#49.<#1.^<!<#48.<#64.^<
    !<#48.<#0.^<!<#48.<#1.^<!#1.-<#57.<#64.^<
    _
?}

#57.<#0.^<#57.<#1.^<!<#56.<#64.^<
#56.<#0.^<#56.<#1.^<!<#55.<#64.^<
#55.<#0.^<#55.<#1.^<!<#54.<#64.^<
#54.<#0.^<#54.<#1.^<!<#53.<#64.^<
#53.<#0.^<#53.<#1.^<!<#52.<#64.^<
#52.<#0.^<#52.<#1.^<!<#51.<#64.^<
#51.<#0.^<#51.<#1.^<!<#50.<#64.^<
#50.<#0.^<#50.<#1.^<!<#49.<
#94.^<

$

```

# Answer
> 2 votes
# 99ISC

99ISC uses an arbitrarily-sized integer-oriented memory. Memory is indexed by a non-negative integer. All values in memory are initialized with their address. Eg. At runtime, address 0 contains value 0 and address 9 contains value 9.

99ISC has two instructions. The first prints out the 99 Bottles of Beer on the Wall routine. Its syntax is a single line, as below. Execution continues with the next line in the program.

```
.

```

The second instruction is a "subtract and branch if not equal to zero" instruction. Its syntax is a single line, as below.

```
x y z

```

`x` is the address of the number to be operated on, `y` is the address of the number being subtracted, and `z` is the next line to execute if the result of the subtraction is not zero. Otherwise, execution proceeds with the next line.

The presence of the "subtract-and-branch-if-not-zero" instruction makes 99ISC an OISC (One Instruction Set Computer) and therefore Turing complete.

Here is a program that erases the first 10 values in memory and then prints the 99 Bottles of Beer on the Wall routine.

```
1 1 0
2 2 0
3 3 0
4 4 0
5 5 0
6 6 0
7 7 0
8 8 0
9 9 0
.

```

And here is a 99ISC interpreter, in Python.

```
def interpret(filename):
    mem = range(0, 10)
    print mem

    with open(filename) as f:
            lines = f.readlines()

    ptr = 0
    while ptr < len(lines):
            line = lines[ptr]

            if line.strip() == ".":
                    for i in range(99,0,-1):
                            text = str(i) + " bottles of beer on the wall, " + str(i) + " bottles of beer.\nTake one down and pass it around, " + str(i-1) + " bottles of beer on the wall.\n\n"
                            print text.replace("0", "No more")
            else:
                    toks = map(int, line.split())
                    mem[toks[0]] = (mem[toks[0]] - mem[toks[1]]) & 0xFF
                    if mem[toks[0]] != 0:
                            ptr = toks[2]
                    else:
                            ptr += 1

```

# Answer
> 1 votes
## Pogo

https://github.com/nrubin29/Pogo

```
method main:void
    declare(integer,i,99)
    while i > 0
        print(i "bottles of beer on the wall")
        math(i - 1) i
    end
end main

```

---
Tags: popularity-contest, interpreter, parsing
---


title: Longest code to reduce words

text:
# Question
Title: Longest code to reduce words
Write a code in your favorite language which reduces words To **`first three characters`**.

```
Input  : One word
Output : First three letters

```

For example

```
INPUT  : ProGramming
OUTPUT : Pro

INPUT  : puZZles
OUTPUT : puZ

INPUT  : BoWling
OUTPUT : BoW

```

**`Output needs to be case sensitive`**

**Rule-1**
All statements should be meaningful and useful.
For example
the C++ snippet below surely increases the score but is unnecessary.
**`The similar code snippets below is banned.`**

```
std::cout<<"abcabc";
std::cout<<"\b\b\b\b\b\b";

```

**Rule-2**
Do not use infinite add-subtract or multiplication-division (or any other kind of) infinite progressions to increase the score.
For example
**`The similar code snippets below is banned.`**

```
if(strcmp(str,"monday")==0)  //The function strcmp() returns 0 if both
                             //strings are same (including NULL character)
cout<<110+1-1+1-1+1-1....inf //110 is ASCII value of 'm'

```

**Winner**
Winner will be chosen on the basis of score (Most score wins) after 4 days from now.
If there is a tie then the one who submitted the answer first is the winner

# Answer
# Befunge 98, 6 bytes

```
~~~,,,

```

Any other statements would be *meaningless and useless*. I could possibly do this though (**18 bytes**):

```
3^,<
 @
 w~^
 0
 :

```

But everything but the `,` and the `~` are *meaningless and useless* because it could be done so much simpler.
> 2 votes

---
Tags: date, code-bowling
---


title: Tell me the moves

text:
# Question
Title: Tell me the moves
Jack and Jane decided to play a game of chess to while away time. Unfortunately, Jack is rather bad at visualizing. He finds it tough to figure the moves possible for a given piece other than a pawn, of course!

Your challenge is to help find Jack the possible options for a given piece (other than a pawn).

In case one has forgotten, the various pieces are denoted by:

* K: King
* Q: Queen
* N: Knight
* B: Bishop
* R: Rook

As an example, in the following image the Knight is located at `d4` and can move to `c2`, `b3`, `b5`, `c6`, `e6`, `f5`, `f3`, `e2`. For a given input:

```
Nd4

```

you would produce:

```
Nc2 Nb3 Nb5 Nc6 Ne6 Nf5 Nf3 Ne2

```

Rules:

* The order of the output doesn't matter as long as all the possible moves are listed
* The possible moves can be separated by whitespaces, newlines or any other delimiter
* The input can be passed to the program as a parameter or via `STDIN`
* Whitespace in the program shall be counted, so make optimum use of it

This is code golf. (Please avoid making use of any tools/utilities specifically designed for the purpose.) The shortest answer wins!

# Answer
> 8 votes
# GolfScript, ~~94~~ 93 characters

My first ever GolfScript program! This took me many an hour of fumbling around not really knowing what I was doing, but I persisted and I think I managed to learn the language basics and golf it fairly well.

Fully golfed:

```
{}/8,{97+.3$-.*:>8,{49+.4$-.*:^2$+.[3<>^*4=>^=>^*!.2$|]"KNBRQ"8$?=*{[5$3$@]""+p}{;}if}/;;}/];

```

Commented and nicer source:

```
{}/              # tIn fIn rIn
8,{97+           #             fTst
  .3$-.*:>       #                  fDif^2 : >
  8,{49+         #                         rTst
    .4$-.*:^     #                              rDif^2 : ^
    2$+.         #                                     ^>+
    [3<          # These    #                              [validK
     >^*4=       # checks   #                                      validN
     >^=         # do not   #                                             validB
     >^*!        # account  #                                                    validR
     .2$|]       # for null #                                                           validQ]
    "KNBRQ"8$?=  # move;    #                          valid
    *            # * does.  #                          validNotNull
    {[5$3$@]""+p}{;}if  # print? #  fDif^2
  }/;;           #        rIn
}/];

```

It may look like Claudiu's answer, which is because I referenced his answer, as well as my (unsubmitted) C solution, while making mine. He provided a good specimen of a (relatively) complex, working GolfScript program, and it helped me learn a lot about the language. So thanks, Claudiu!

Being new to GolfScript still, if you guys have any feedback, I'd appreciate hearing it!

# Answer
> 12 votes
# Python, ~~217~~ ~~212~~ ~~220~~ ~~217~~ 213 characters

Tied the 213-byte Mathematica solution

```
R=range(8)
def f((p,x,y)):
 for a in R:
    for b in R:
     A,B=abs(a-ord(x)+97),abs(b-ord(y)+49);C=max(A,B);r=(A+B==3and C<3,C<2,A*B<1,A==B,0)
     if(r['NKRBQ'.index(p)],any(r[1:]))[p=='Q']*C:print p+chr(a+97)+chr(b+49)

```

I started off by generating all valid moves but that grew too large so the approach is quite similar to the Mathematica one.

```
>>> f("Nd4")
Nb3
Nb5
Nc2
Nc6
Ne2
Ne6
Nf3
Nf5
>>> f("Qa1")
Qa2
Qa3
Qa4
Qa5
Qa6
Qa7
Qa8
Qb1
Qb2
Qc1
Qc3
Qd1
Qd4
Qe1
Qe5
Qf1
Qf6
Qg1
Qg7
Qh1
Qh8

```

# Answer
> 10 votes
## Mathematica, ~~278~~ ~~272~~ ~~264~~ ~~260~~ ~~215~~ 213 characters

```
f=(FromCharacterCode@Flatten[Table[c=Abs[#2-x];d=Abs[#3-y];b=c==d;r=#2==x||#3==y;If[Switch[#-75,0,c~Max~d<2,-9,b,7,r,6,b||r,3,!r&&c+d==3],{p,x,y},##&[]],{x,97,104},{y,49,56}]&@@ToCharacterCode@#,1]~DeleteCases~#)&

```

Ungolfed version:

```
f[pos_] := (
  {piece, u, v} = ToCharacterCode@pos;
  board = Flatten[Table[{piece, i + 96, j + 48}, {i, 8}, {j, 8}], 1];
  DeleteCases[
    FromCharacterCode[
      Cases[board, {_, x_, y_} /; Switch[p,
        75, (* K *)
        ChessboardDistance[{x, y}, {u, v}] < 2,
        66, (* B *)
        Abs[u - x] == Abs[v - y],
        82, (* R *)
        u == x || v == y,
        81, (* Q *)
        Abs[u - x] == Abs[v - y] || u == x || v == y,
        78, (* N *)
        u != x && v != y && ManhattanDistance[{x, y}, {u, v}] == 3
        ]
      ]
    ],
    pos (* remove the input position *)
  ]
)&

```

Example usage:

```
f["Nd4"]
> {"Nb3", "Nb5", "Nc2", "Nc6", "Ne2", "Ne6", "Nf3", "Nf5"}

```

The ungolfed version creates a full board, and then selects correct positions with `Cases`, whereas the golfed version drops invalid moves immediately in the `Table` command by issuing `##&[]`, which simply vanishes.

# Answer
> 10 votes
# Haskell ~~225 220 208 205 200~~ 182

```
f=fromEnum
m[p,a,b]=[[p,c,r]|c<-"abcdefgh",r<-"12345678",let{s=abs$f a-f c;t=abs$f b-f r;g"K"=s<2&&t<2;g"Q"=g"B"||g"R";g"N"=s+t==3&&(s-t)^2<2;g"B"=s==t;g"R"=s<1||t<1}in s+t>0&&g[p]]

```

~~It's going to be difficult to touch Mathematica when that has chess moves built in :rollseyes: (well played m.buettner)~~ I take it all back. Beating Mathematica by 31!

Latest edit: replaced case with a function, inlined filter into comprehension, to beat the entry in R ;)

usage:

```
ghci> m "Nd4"
["Nb3","Nb5","Nc2","Nc6","Ne2","Ne6","Nf3","Nf5"]

```

Ungolfed (corresponds to 208 char version before 'u' was inlined):

```
f=fromEnum -- fromEnum is 'ord' but for all enum types,
           -- and it's in the prelude, so you don't need an extra import.
u piece dx dy= -- piece is the character eg 'K', dx/dy are absolute so >=0.
  dx+dy > 0 && -- the piece must move.
  case piece of
    'K'->dx<2&&dy<2         -- '<2' works because we already checked dx+dy>0
    'Q'->dx<1||dy<1||dx==dy -- rook or bishop move. see below.
    'N'->dx+dy == 3 &&      -- either 2+1 or 3+0. Exclude the other...
         (dx-dy)^2 < 2      -- 1^2 or 3^2, so valid move is '<2', ie '==1'
    'B'->dx==dy             -- if dx==dy, dx/=0 - we checked that.
                            -- other moves with dx==dy are along diagonal
    _->dx<1||dy<1           -- use _ not 'R' to save space, default case is
                            -- the rook. '<1' saves chars over '==0'.
                            -- Again, dx==dy==0 edge case is excluded.
m[piece,file,rank]=       -- the move for a piece. 'parse' by pattern match.
 filter(                    -- filter...
  \[_,newfile,newrank]->    -- ...each possible move...
    u piece                 -- ...by, as everyone noticed, converting char..
      (abs$f file-f newfile) -- differences to absolute dx, dy differences,..
      (abs$f rank-f newrank)) -- and then using special routines per piece.
    [[piece,newfile, newrank] -- the output format requires these 3 things.
      |newfile<-"abcdefgh",newrank<-"12345678"] -- and this just generates moves.

```

# Answer
> 8 votes
# Bash, 238

```
B={19..133..19}\ {21..147..21};K=1\ {19..21};N='18 22 39 41';R={1..7}\ {2..14..2}0;Q=$B\ $R
a=${1%??};b=$[20#${1:1}-200];c=`eval{,} echo '$'$a`;d=({a..h})
for i in $c -${c// / -};do echo $a${d[$[(i+=b)/20]]}$[i%20];done|grep '[a-h][1-8]$'

```

# How it works

* The idea is to represent every field on the board by a numeric value, taking its coordinates as a base-20 number and subtracting 200. This way, `a1` becomes `20 * 10 + 1 - 200 = 1`, `h8` becomes `20 * 17 + 8 - 200 = 148`, etc.

Now, the possible moves of the Bishop can be represented by (positive or negative) multiples of 19 – same amount of steps up (+20) and to the left (-1) – or 21 – same amount of steps up (+20) and to the right (+1).

The figure's placement after the move is simply the sum of its original position and the movement. After adding those numbers, we have to check if their sum corresponds to a valid field on the board.

Since the base (20) is more than twice as big as the highest possible number (8), the sum cannot wrap around the board, e.g., moving *Bh1* seven steps to the right and up will result in an invalid board position.
* The line

```
B={19..133..19}\ {21..147..21};K=1\ {19..21};N='18 22 39 41';R={1..7}\ {2..14..2}0;Q=$B\ $R

```

enumerates all possible moves of the pieces that are represented by positive numbers.
* The commands

```
a=${1%??};b=$[20#${1:1}-200];c=`eval{,} echo '$'$a`;d=({a..h})

```

stores the piece's identifier in variable *a*, the original position's numeric representation in *b* and the letters *a* to *h* in the array *d*.

After brace expansion, `eval{,} echo '$'$a` becomes `eval eval echo '$'$a` (doubly evil), which evaluates to, e.g., `eval echo $K`, which evaluates to `echo 1 19 20 21`.
* `for i in $c -${c// / -};do …; done` loops over all possible movements and their negative counterparts.
* `echo $a${d[$[(i+=b)/20]]}$[i%20]` gives the final position after the movement.
* `grep '[a-h][1-8]$'` makes sure that we have a valid board position.

# Answer
> 7 votes
## C ~~634~~ ~~632~~ ~~629~~ ~~625~~ 600 chars

```
#define F for(;i<4;i++){
#define B ;}break;
#define O x=X,y=Y,
P,X,Y,c,r,x,y,i=0, N[8][2]={{-2,1},{-1,2},{1,2},{2,1},{-2,-1},{-1,-2},{1,-2},{2,-1}},S[4][2]={{1,0},{0,1},{-1,0},{0,-1}},D[4][2]={{-1,1},{-1,-1},{1,1},{1,-1}};
C(){return((0<=c)&(c<8)&(0<r)&(r<9))?printf("%c%c%d ",P,c+'a',r):0;}
M(int*m){c=m[0]+x,r=m[1]+y;C()?x=c,y=r,M(m):0;}
main(int a,char**v){char*p=v[1];P=*p,X=p[1]-97,Y=p[2]-48; switch(P){case 75:F c=S[i][1]+X,r=S[i][0]+Y,C(),c=D[i][1]+X,r=D[i][0]+Y,C()B case 81:F O M(D[i]),O M(S[i])B case 78:for(;i<8;i++){c=N[i][1]+X,r=N[i][0]+Y,C()B case 66:F O M(D[i])B case 82:F O M(S[i])B}}

```

Any suggestions on how to improve this? This is my first time submitting an answer.

# Answer
> 7 votes
# Golfscript, ~~144~~ 135 characters

Instead of continuing to try golfing my Python solution, I translated it into Golfscript:

```
{}/49-:y;97-:x;:N;8,{.x-abs:A
8,{.y-abs:B@[\]$1=:C[B
A+3=\3<&2C>B
A*1<B
A=]81N={(;{|}*}{"NKRB"N?=}if
C*{[N
2$97+@49+]''+p}{;}if
A}/;;}/

```

Straightforward translation without much golfing so it can most likely be whittled away further. Takes input from stdin without a newline, try it here (1st two lines are to mimic stdin).

# Answer
> 3 votes
## Haskell, ~~300~~ 269 chars

Thanks to bazzargh for help with losing 31 characters...

```
import Data.Char
f x=filter(x#)[x!!0:y|y<-[v:[w]|v<-"abcdefgh",w<-"12345678"],y/=tail x]
a%b=abs(ord a-ord b)
x#y=let{h=(x!!1)%(y!!1);v=(x!!2)%(y!!2);m=max h v;n=min h v}in case(x!!0)of{'N'->m==2&&n==1;'K'->m==1;'B'->h==v;'R'->n==0;'Q'->('R':tail x)#y||('B':tail x)#y}

```

Same algorithm as the Mathematica version. Sample output from ghci:

```
*Main> f "Nd4"
["Nb3","Nb5","Nc2","Nc6","Ne2","Ne6","Nf3","Nf5"]
*Main> f "Ni9"
["Ng8","Nh7"]

```

(You didn't ask for sanity checking!)

# Answer
> 1 votes
# Haskell , 446 chars

```
import Data.Char
a=[-2,-1,1,2]
b=[-1,1]
d=[1..8]
e=[-8..8]
g=[-1..1]
h 'N' c r=[(c+x,r+y)|x<-a,y<-a,3==(sum$map abs[x, y])]
h 'B' c r=[(c+x*z,r+y*z)|x<-b,y<-b,z<-d]
h 'R' c r=[(c+x,r)|x<-e]++[(c,r+y)|y<-e]
h 'Q' c r=h 'B' c r++h 'R' c r
h 'K' c r=[(c+x,r+y)|x<-g,y<-g]
l s=ord s-96
m n=chr$n+96
k ch (c,r)=ch:m c:[intToDigit r]
f (x,y)=all(`elem`[1..8])[x, y]
i n c r=map(k n).filter(/=(c,r)).filter f$h n c r
j s=i(s!!0)(l$s!!1)(digitToInt$s!!2)

```

Called using the `j` function

```
j "Nd4"

```

I haven't worked with Haskell in a few months, so it didn't end up being as short as most of the other solutions, but I'm sure there are some optimizations to made, mainly with `h`. I might shorten it in a bit.

# Answer
> 1 votes
# q & k \[311 262 chars\]

There is a potential of reducing some more characters. I will be reducing it in next iteration.

```
k)o:{n:#m:&(#x)##y;((),x)[m],'n#y}

k)a:`$"c"$(o/)c:+(97;49)+/:!8

k)r:{{|x@<x}'?,/{o[x]y}'[x](|"c"$c)}
k)k:{"c"$(6h$x)+/:(o/)2 3#-1 0 1}
k)n:{"c"$(6h$x)+/:(|:'t),t:o[-1 1;2 2]}
k)b:{"c"$(6h$x)+/:(n,'n),n,'|n:-8+!17}
k)q:{,/(r;b)@\:x}

d:{(`$("rknbq"!(r;k;n;b;q))[x]y)except`$y}
g:{a inter d[x 0]@1_x}

```

### Usage

Rook

```
g"ra1"
`a2`a3`a4`a5`a6`a7`a8`b1`c1`d1`e1`f1`g1`h1

```

King

```
g"ka1"
`a2`b1`b2

```

Knight

```
g"na1"
`b3`c2

```

Bishop

```
g"ba1"
`b2`c3`d4`e5`f6`g7`h8

```

Queen

```
g"qa1"
`a2`a3`a4`a5`a6`a7`a8`b1`b2`c1`c3`d1`d4`e1`e5`f1`f6`g1`g7`h1`h8

```

# Answer
> 0 votes
## Haskell (hypothetical), 248 chars

```
import Data.Char
f x=filter(o x)[x!!0:y|y<-[v:[w]|v<-"abcdefgh",w<-"12345678"],y/=tail x]
d a b=abs(ord a-ord b)
h x y=(c*(d(x!!1)(y!!1))-(d(x!!2)(y!!2)))+200*c
 where c=d (x!!0)'A'
o x y=elem(chr(h x y))"ਲ਼ੁߏߚߙÈേെ൅ൄൃ൙൪ൻඌඝථ඿౿౾౽౼౻౺౹ಐಏಠಞರಭೀ಼೐ೋೠ೚೰೩"

```

Unfortunately, every Haskell compiler I can get my hands on right now has problems with Unicode string literals. Here's the (longer) version that actually works:

```
import Data.Char
f x=filter(o x)[x!!0:y|y<-[v:[w]|v<-"abcdefgh",w<-"12345678"],y/=tail x]
d a b=abs(ord a-ord b)
h x y=(c*(d(x!!1)(y!!1))-(d(x!!2)(y!!2)))+200*c
 where c=d (x!!0)'A'
o x y=elem(chr(h x y))"\2611\2625\1999\2010\2009\200\3399\3398\3397\3396\3395\3394\3393\3417\3434\3451\3468\3485\3502\3519\3199\3198\3197\3196\3195\3194\3193\3216\3215\3232\3230\3248\3245\3264\3260\3280\3275\3296\3290\3312\3305"

```

The definition `h x y=...` is a hash function; valid moves will hash to character numbers that are in the 41-character string. This gets rid of the need for a "case" statement or equivalent.

I'm not planning to work further on this right now. It would be fun to see if someone can use a hash function in a more concise language to make a shorter solution.

# Answer
> 0 votes
# R, 203 chars

```
f=function(p,x,y){x=which((l=letters)==x);X=rep(1:8,8);Y=rep(1:8,rep(8,8));A=abs(X-x);L=abs(Y-y);B=A==L;R=!A|!L;i=switch(p,N=A+L==3&A&L,R=R,B=B,Q=R|B,K=(R|B)&A<2&L<2)&A+L>0;paste(p,l[X[i]],Y[i],sep="")}

```

Ungolfed version:

```
f = function(p,x,y) {
  x = which(letters == x)  # Gives index between 1 and 8.
  X = rep(1:8, 8)          # 1,2,...,7,8,1,2,.... (8x8).
  Y = rep(1:8, rep(8,8))   # 1,1,...2,2,.....,8,8 (8x8).
  dx = abs(X-x)
  dy = abs(Y-y)
  B = (dx == dy)           # Bishop solutions
  R = (!dx | !dy)          # Rock solutions
  i = switch(p,
             N=dx+dy==3 & dx & dx,  # Sum of dist. is 3, dx and dy must be <> 0.
             R=R,
             B=B,
             Q=R|B,                 # Queen is merge of rock and bishop.
             K=(R|B) & dx<2 & dy<2  # King's distance is < 2.
             ) & (dx+dy > 0)        # Exclude start field.

  paste(p, letters[X[i]], Y[i], sep="")
}

```

Usage:

```
> f('N', 'a', 3)
[1] "Nb1" "Nc2" "Nc4" "Nb5"

```

The solution is even good readable. However I added some parentheses and comments for readers unfamiliar with R code (on the ungolfed version).

---
Tags: code-golf, chess
---


# Question
Title: How much bounty is out on Stackoverflow?
**Task:**

You are an amazing programmer and Stackoverflow-answerer, and you decide to answer every question with a bounty on Stackoverflow. You are so good, that you manage to get all the bounties in all the questions. While you wait for the rep to come flooding in, you write a program that goes and find out what the total amount of rep is in all those bounties.

**Rules:**

* When run,
    + Your program will navigate through the featured tab on Stack Overflow.
    + It will scrape out the value of each bounty,
    + Then it will add it up and display the total
* It has to download data from anywhere on SO (and only SO), but I would recommend using https://stackoverflow.com/questions?pagesize=50&sort=featured , as it is only about 10 pages
* This is , so the shortest code wins

# Answer
> 23 votes
## JavaScript - ~~176~~ ~~133~~ ~~130~~ ~~108~~ 106

```
function f()(t+=$("[title~=an]").text(),u=$("[rel*=x]")[0])?$("html").load(u.href,f):alert(eval(t));f(t=0)

```

*Edit 1: trimmed some selectors down and used the `?:` suggestion from Google's Closure Compiler (via @Sirko - thanks)*

*Edit 2: initialise `s` inside `d` and initialise `t` as `0` instead of `""`*

*Edit 3: realised I don't actually need to target a specific container and can sweep the whole document, which gets rid of a bunch of `.find` calls and an unnecessary selector (plus the variable holding it)*

*Edit 4: shove the `t` initialiser in the function call to avoid a `;` (it'll get hoisted to the top anyway) and squash the function down to one statement (combine two statements into one inside the ternary statement condition) to drop the `{}`*

**Note**: I'm not sure if it's cheating, but this has to be run from a console window of a browser already pointing at `http://stackoverflow.com/questions?page=1&sort=featured`. It relies on the fact that **jQuery** and the appropriate paging links are available on the page itself. Also, it only appears to work in **Firefox** and not in IE or Chrome.

**Output** (at time of posting):

```
38150 (in an alert dialog)

```

**Exploded/commented**:

```
function f()
    //concat all the bounty labels to t (they take the format "+50")
    //happens to be elements with title attribute containing word 'an'
    (t+=$("[title~=an]").text(),
    //find the "next" (has rel=next attribute) button
    u = $("[rel*=x]")[0])
        ?
        //if there is a next button, load it, and then recurse f again
        $("html").load(u.href,f)
        :
        //else eval the 0+a+b+...+z tally and alert the result
        alert(eval(t))
//kick off the initial scrape (and simultaneously init the total tally)
f(t=0)

```

# Answer
> 21 votes
## Python - ~~232~~, ~~231~~, ~~195~~, ~~183~~, ~~176~~, 174

Parses the HTML from https://stackoverflow.com/questions?sort=featured using regular expressions.

The upper bound of `range` in the `for` loop *must* be `number of pages + 1` or else the code will raise `HTTPError` because of 404s. Default number of results per-page is 15, which is what the code uses (omitting `?pagesize=50` saves on characters and is just as effective).

Thanks to **@Gabe** for the tip on reducing char count even further.

**Golfed**:

```
import requests,re;print sum(sum(map(int,re.findall(r"<.*>\+(\d+)<.*>",requests.get("https://stackoverflow.com/questions?sort=featured&page=%u"%i).text)))for i in range(1,33))

```

**Output** (at time of posting):

```
37700

```

**Un-golfed**:

Here's a somewhat un-golfed version that should be a bit easier to read and understand.

```
import requests, re

print sum(
          sum(
              map( int,
                   re.findall( r"<.*>\+(\d+)<.*>",
                               requests.get( "https://stackoverflow.com/questions?sort=featured&page=%u" % i).text
                   )
              )
          ) for i in range( 1, 33 )
      )

```

# Answer
> 18 votes
# Rebol - ~~164~~ ~~133~~ 130 (139 with 404 check)

Parses the html using the `parse` sub-language of Rebol. Checks the first 98 pages. I realised I have the same constraint as the python solution - too many repeats hit 404 errors and stop the execution. Thanks to @rgchris for many improvements! Updated to check up to 98 pages.

`s: 0 repeat n 99[parse read join http://stackoverflow.com/questions?sort=featured&page= n[15[thru{>+}copy x to{<}(s: s + do x)]]]s`

With error checking for 404s (139):

`s: 0 repeat n 99[attempt[parse read join http://stackoverflow.com/questions?sort=featured&page= n[15[thru{>+}copy x to{<}(s: s + do x)]]]]s`

**Test**

```
>> s: 0 repeat n 20[parse read join http://stackoverflow.com/questions?sort=featured&page= n[15[thru{>+}copy x to{<}(s: s + do x)]]]s
== 23600

>> s: 0 repeat n 99[attempt[parse read join http://stackoverflow.com/questions?sort=featured&page= n[15[thru{>+}copy x to{<}(s: s + do x)]]]]s
Script: none Version: none Date: none
== 36050

```

**Explanation**

Rebol ignores whitespace, hence you can put it all on one line like that if you choose. PARSE takes two inputs, and the first argument *(`read join ...`)* is fairly self-explanatory. But here are some comments on the parse dialect instructions, in a more traditional indentation:

```
s: 0
repeat n 99 [
    parse read join http://stackoverflow.com/questions?sort=featured&page= n [
        ;-- match the enclosed pattern 15 times (the rule will fail politely when there are less entries)
        15 [
            ;-- seek the match position up THRU (and including) the string >+
            thru {>+}
            ;-- copy contents at the current position up TO (but not including) <
            copy x to {<}
            ;-- (Basically, run some non-dialected Rebol if this match point is reached) the do is a bit dangerous as it runs the string as code
            (s: s + do x)
        ]
    ]
]
;-- evaluator returns last value, we want the value in S
;-- (not the result of PARSE, that's a boolean on whether the end of input was reached)
s

```

# Answer
> 11 votes
# Ruby, 260

```
require'open-uri'
require'zlib'
i=b=0
d=''
until /"has_more":f/=~d
i+=1
d=Zlib::GzipReader.new(open("http://api.stackexchange.com/2.2/questions/featured?site=stackoverflow&page=#{i}&pagesize=100")).read
b+=d.scan(/"bounty_amount":(\d+)/).map{|x|x[0].to_i}.reduce :+
end
p b

```

Uses the Stack Exchange API.

Output (as of time of original post):

```
37200

```

I'm not counting the `&pagesize=100` in the character count, because it works without it, but I just added that for convenience while testing. If you remove that, it does the same thing (except it eats more quota and takes slightly longer).

# Answer
> 8 votes
# Rebmu - ~~108~~107

```
rtN99[parseRDrj[http://stackoverflow.com/questions?sort=featured&page=N][15[thru{>+}copyXto{<}(a+JdoX)]]]j

```

**Test** (at 19:05 AEST)

```
>> rebmu [rtN99[parseRDrj[http://stackoverflow.com/questions?sort=featured&page=N][15[thru{>+}copyXto{<}(a+JdoX)]]]j]
Script: none Version: none Date: none
== 79200

```

Rebmu looks rather cryptic, but it is quite readable once you get the hang of it. Let's start by unmushing it and laying it out properly.

```
rt n 99 [
    parse rd rj [
        http://stackoverflow.com/questions?sort=featured&page= n
    ][
        15 [
            thru {>+}
            copy x to {<}
            (a+ j do x)
        ]
    ]
]
j

```

Rebmu is a dialect of Rebol so you can see the similarities in the solution. Rebmu can't reduce the size of every statement yet, but it is an evolving language. Thanks again to @rgchris for the improvements to my first attempt.

# Answer
> 6 votes
# Ruby - 197

Short version:

```
require 'nokogiri'
require 'open-uri'
s=0
(1..33).each{|p|Nokogiri::HTML(open("http://stackoverflow.com/questions?page=#{p}&sort=featured")).css('.bounty-indicator').each{|b|s+=b.content.to_i}}
p s

```

Human friendly version:

```
require 'nokogiri'
require 'open-uri'
s=0
(1..33).each do |p|
    Nokogiri::HTML(open("http://stackoverflow.com/questions?page=#{p}&sort=featured")).css('.bounty-indicator').each do |b|
        s += b.content.to_i
    end
end
puts s

```

And answer - `39700`

# Ruby with script parameters - 139

```
require 'nokogiri'
require 'open-uri'
s=0
(1..33).each{|p|Nokogiri::HTML(open(ARGV[0]+p.to_s)).css(ARGV[1]).each{|b|s+=b.content.to_i}}
p s

```

To run this from bash just type

```
ruby code_golf_stack_overflow2.rb http://stackoverflow.com/questions?sort=featured\&page= .bounty-indicator

```

# Answer
> 6 votes
## PHP, ~~134~~, ~~131~~, 127

`while($q=array_sum(preg_filter('#.*>\+#',0,file("http://stackoverflow.com/questions?sort=featured&page=".++$n))))$s+=$q;echo$s;`

Will loop through **all** pages, `pagesize` is not set to save bytes so more `GET`s.

Very Very Dirty, but... taking advantage of `PHP`'s "flaws" !

* no space after `echo`
* `while` stops at assignment
* output after `RegEx` replace is a string starting with the bounty amount
* `array_sum()` adds up strings
* `$n` and `$s` are initialized, but starting from nothing is equiv. as starting from zero
* etc...

# Answer
> 6 votes
## PHP - 121 bytes

```
<?for(;preg_filter('/>\+(\d+)/e','$t+=\1',@file('http://stackoverflow.com/questions?sort=featured&page='.++$n)););echo$t;

```

Using a regex 'eval' modifier, to avoid using `array_sum` or similar. Seems to be the shortest solution among valid entries.

# Answer
> 5 votes
# Javascript - ~~129~~ ~~119~~ ~~110~~ 107 characters

## EDIT: INVALID ANSWER! This only handles the "Top featured questions", which only has a fraction of them. Alconja's answer is more valid.

```
s="#mainbar";t="";eval("$(s).find('.bounty-indicator').each(function(){t+=this.innerHTML});alert(eval(t))")

```

Execute on https://stackoverflow.com/?tab=featured in a console window. Based on the solution by Alconja.

Golfed it a bit more by removing unneeded whitespaces.

Used eval to remove the function call, clearing another 9 characters.

cleared out some more unneeded whitespace.

# Answer
> 5 votes
**Bash 206**

optimizations possible, too lazy

```
s=0;for i in `seq 1 11`;do for j in `wget -q -O - "http://stackoverflow.com/questions?pagesize=50&sort=featured&page=$i" | grep -o -E "bounty worth [0-9]*" | grep -o -E "[0-9]*"`;do s=$(($s+$j));done;done;echo $s

```

result:

```
39450

```

# Answer
> 3 votes
# Java, 540 chars

***Warning: the number of active bounties is ~470. This code will access a page on stackoverflow that many times. It may get you in trouble with them for making so many data requests.***

```
import java.io.*;import java.net.*;public class B{public static void main(String[]A){String u="http://stackoverflow.com/questions",d;Long i,s=i=0L,n=i.parseLong(o(u).replaceAll("^.*b.>(\\d+).*$","$1"));while(i++<n){d=o(u+"?pagesize=1&sort=featured&page="+n).replaceAll("^.*ion.>.(\\d+).*$","$1");s+=d.matches(".*\\D.*")?0:n.parseLong(d);}System.out.print(s);}static String o(String s){String d="";try{BufferedReader r=new BufferedReader(new InputStreamReader(new URL(s).openStream()));while((s=r.readLine())!=null)d+=s;}finally{return d;}}}

```

My output was `23400`, but when I ran @TonyH's code, I got `37550`. Bad news.

Pretty code:

```
import java.io.*;
import java.net.*;

public class StackOverflowBounty {

    public static void main(String[] args) {
        String u = "http://stackoverflow.com/questions", d;
        Long i, s = i = 0L, n = i.parseLong(o(u).replaceAll("^.*b.>(\\d+).*$", "$1"));
        while (i++ < n) {
            d = o(u + "?pagesize=1&sort=featured&page=" + n).replaceAll("^.*ion.>.(\\d+).*$", "$1");
            s += d.matches(".*\\D.*") ? 0 : n.parseLong(d);
        }
        System.out.print(s);
    }

    static String o(String s) {
        String d = "";
        try {
            BufferedReader r = new BufferedReader(new InputStreamReader(new URL(s).openStream()));
            while ((s = r.readLine()) != null) {
                d += s;
            }
        } finally {
            return d;
        }
    }
}

```

The way this works is simple. It reads from the url `http://stackoverflow.com/questions"` to determine the number of questions that have bounties (note: if the number increases, the program fails, but if it drops, it works fine). It searches for this number using the regex: `b.>(\\d+)`. This has worked in all tests to date, but if someone asked a question that matches that regex, this might not work.

Then, we open the url `http://stackoverflow.com/questions?pagesize=1&sort=featured&page=` \+ `current question #`. In other words, we open a new page for each featured question, and force the number of questions to be only `1`, so we will get them all. The reputation part will always match `ion.>.(\\d+)`, so I use that to find it. I split the operation into two parts so that I could cheaply check if the number of questions reduced (ie the string returned is not an integer).

Then, we sum up all the reputation and print it.

It took about 3 minutes and 20 seconds to run on my machine.

---

Does anyone know why it isn't printing the right number?

# Answer
> 2 votes
## C# - 407

```
class B{void Main(string[] a){var o=0;for(int i=1;i<11;i++){var r=((System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(new Uri(string.Format(a[0]+"&page={0}",i)))).GetResponse();if(r.ContentLength>0){using(var s=new StreamReader(r.GetResponseStream()))foreach(Match m in Regex.Matches(s.ReadToEnd(),"bounty worth (.+?) "))o+=int.Parse(m.Value.Substring(m.Value.IndexOf('h')+2));}}Console.Write(o);}}

```

Using Stackoverflow.com. Same as below, except no Gzip decompressing and different regex.

**Test**

```
> prog.exe http://stackoverflow.com/questions?pagesize=50&sort=featured
38150

```

Weirdly, getting a different value than below.

---

## C# - 496

This uses api.stackexchange which is gzipped and json.

```
using System.IO.Compression;class B{void Main(string[] a){var o=0;for(int i=1;i<11;i++){var r=((System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(new Uri(string.Format(a[0]+"&page={0}",i)))).GetResponse();if(r.ContentLength>0)using(var s=new StreamReader(new GZipStream(r.GetResponseStream(),CompressionMode.Decompress)))foreach(Match m in Regex.Matches(s.ReadToEnd(),@"bounty_amount"":(.+?),"))o+=int.Parse(m.Value.Substring(m.Value.IndexOf(':')+1).Replace(",",""));}Console.Write(o);}}

```

**Unminified:**

```
using System.IO.Compression;

class B
{
    void Main(string[] a)
    {
        var o = 0;
        for (int i=1; i<11; i++) {
            var w = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(new Uri(string.Format(a[0]+"&page={0}",i)));
            if(w.GetResponse().ContentLength > 0)
                using(var s = new StreamReader(new GZipStream(w.GetResponse().GetResponseStream(),CompressionMode.Decompress)))
                    foreach(Match m in Regex.Matches(s.ReadToEnd(), @"bounty_amount"":(.+?),"))
                        o += int.Parse(m.Value.Substring(m.Value.IndexOf(':')+1).Replace(",", ""));
        }
        Console.Write(o);
    }
}

```

**Test**

Default pagesize:

```
> prog.exe http://api.stackexchange.com/2.2/questions/featured?site=stackoverflow
25300

```

Pagesize=100:

```
> prog.exe "http://api.stackexchange.com/2.2/questions/featured?site=stackoverflow&pagesize=100"
37400

```

# Answer
> 2 votes
# jQuery 191

```
i=0;function f(p){$.get('//api.stackexchange.com/2.2/questions/featured?site=stackoverflow&page='+p,function(d){for(x in d.items)i+=d.items[x].bounty_amount;d.has_more?f(p+1):alert(i)})};f(1)

```

It works from anywhere in stackexchange(and many other sites), no need to be in a specific page as in @Alconja/@NateKerkhofs answers

# Answer
> 2 votes
## PHP - 139

**Golfed:**

```
<?php
$a=file_get_contents('http://stackoverflow.com/?tab=featured');preg_match_all('/n">\+([0-9]+)<\/div>/',$a,$r);echo array_sum($r[1]);

```

**Ungolfed - 147**

Simple `file_get_contents` / `preg_match` / `array_sum`

```
<?php
$a = file_get_contents('http://stackoverflow.com/?tab=featured');
preg_match_all('/n">\+([0-9]+)<\/div>/', $a, $r);
echo array_sum($r[1]);

```

**Test:**

> php run.php
>
> 10250

# Answer
> 2 votes
# Python (174 characters):

Expanding on the python answer above (don't have enough karma to comment):

```
import requests,re;print sum(sum(map(int,re.findall(r"<.*>\+(\d+)<.*>",requests.get("http://stackoverflow.com/questions?sort=featured&page=%u"%i).text)))for i in range(1,33))

```

Requests in lieu of urllib cuts down on 2 chars.

# Answer
> 2 votes
# Bash 174

Based on https://codegolf.stackexchange.com/a/25180/7664:

```
s=0;for i in {1..11};do for j in `wget -qO- "stackoverflow.com/questions?pagesize=50&sort=featured&page=$i"|cut -d' ' -f18|egrep '^[0-9]+$'`;do s=$(($s+$j));done;done;echo $s

```

# Answer
> 1 votes
# Ruby (176 chars):

Following Tony H.'s example of using hard-coded page numbers, here's what I got:

```
require'open-uri';b=0;(1..29).each{|i|d=open("http://stackoverflow.com/questions?sort=featured&page=#{i}").read;b+=d.scan(/<.*>\+(\d+)<.*>/).map{|x|x[0].to_i}.reduce 0,:+};p b

```

gave me 35300 at the time of writing.

---
Tags: code-golf, internet
---