title: Alphabet cannon

text:
# Question
Title: Alphabet cannon
A cannonball is fired so that in the first eyeblink of its flight it ascends by `N` treetops, during the second eyeblink by `N-1` treetops, etc until it reaches the highest point of its trajectory. Then it starts falling by 1, 2, etc treetops per eyeblink until it hits the ground. At the same time the cannonball is moving horizontally with a constant velocity of 1 treetop/eyeblink.

Your task is to draw the trajectory with consecutive letters from the English alphabet. If you run out of letters, start again from `'A'`. Write a function or a program. The input is an integer `N` (`1≤N≤15`). The output can be a character matrix in any reasonable form, for instance a newline-separated string or a list of strings. Letters can be all lowercase or all uppercase. Extra leading and trailing spaces are allowed. Standard loopholes are forbidden. Shorter code is better.

```
in:
5
out:
    OP
   N  Q
   M  R
  L    S
  K    T
  J    U
 I      V
 H      W
 G      X
 F      Y
E        Z
D        A
C        B
B        C
A        D

in:
1
out:
AB

```

# Answer
> 8 votes
# 05AB1E, ~~33~~ ~~32~~ ~~29~~ 28 bytes

```
>*As∍2ä`R)ζRIL£vyε`N·úJ])˜.c

```

Try it online!

**Explanation**

```
>*                             # push input*(input+1)
  As∍                          # take that many characters from the alphabet (with wrap)
     2ä                        # split in 2 parts
       `R)                     # reverse the second part
          ζ                    # zip (gives a list of pairs)
           R                   # reverse
            IL£                # split into parts of sizes equal to [1,2...]
               vy              # for each (part y, index N)
                 ε             # for each pair in that part
                  `N·úJ        # insert N*2 spaces between the characters
                       ]       # end loops
                        )˜     # wrap in a flattened list
                          .c   # format as lines padded to equal length

```

# Answer
> 8 votes
# Stax, 29 24 bytes

```
╦'♫ΓqπL⌂δ@╚n>DI∙Q┴òkεwö╔

```

Run and debug it online

The corresponding ascii representation of the same program is this.

```
VA*xRr:m|/xH({rix/|1*_%:T)mMm

VA*                             repeat alphabet input times
   xRr:m                        [x ... 1, 1 ... x] where x=input
        |/xH(                   get consecutive substrings of specified sizes
             {           m      map substrings using block
              ix<|1*            reverse string if index<x
                    _%:T)       left-pad to appropriate triangular number
                          Mm    transpose and output

```

# Answer
> 7 votes
# R, ~~169~~ ~~163~~ ~~161~~ ~~153~~ ~~150~~ ~~110~~ 109 bytes

This approach fills in a matrix and then prints the matrix.

**Golfed**

```
function(n)write(`[<-`(matrix(" ",M<-2*n,k<-sum(1:n)),cbind(rep(1:M,c(n:1,1:n)),c(k:1,1:k)),LETTERS),1,M,,"")

```

Thanks @Giuseppe for 153.

Thanks @JDL for 150.

See @Giuseppe's comment for 112, and some edits for 110 now 109. Rip original code.

```
function(n){a=matrix(" ",M<-2*n,k<-sum(1:n))
Map(function(x,y,z)a[x,y]<<-z,rep(1:M,c(n:1,1:n)),c(k:1,1:k),head(LETTERS,2*k))
cat(rbind(a,"
"),sep="")}

```

If plotting a valid output then 73 bytes

```
function(n,k=sum(1:n))plot(rep(1:(2*n),c(n:1,1:n)),c(1:k,k:1),pc=LETTERS)

```

# Answer
> 6 votes
# Python 2, ~~140~~ ~~135~~ 133 bytes

```
lambda n:[' '*(n-j)+chr(~-i%26+65)+'  '*j+chr((n*-~n-i)%26+65)for i,j in zip(range(n*-~n/2,0,-1),sum([-~i*[i]for i in range(n)],[]))]

```

Try it online!

# Answer
> 5 votes
# MATL, 29 bytes

```
,G:tPY"tf1Y2y@?tn+P])Z?]Pv1X!

```

Try it online!

### How it works

```
,        % Do twice
  G:     %   Push [1 2 ... n], where n is the input
  tP     %   Duplicate, flip: pushes [n n-1 ... 1]
  Y"     %   Run-length decoding: gives vector with n ones, n-1 twos ... (*)
  tf     %   Duplicate, find: gives [1 2 3 ... n*(n-1)/2] (**)
  1Y2    %   Push string 'ABC...Z'
  y      %   Duplicate from below: pushes [1 2 3 ... n*(n-1)/2]  again
  @?     %   If we are in the second iteration
    tn   %     Duplicate, length: pushes n*(n-1)/2
    +    %     Add: gives [n*(n-1)/2+1 n*(n-1)/2+2 ... n*(n-1)*2]
    P    %     Flip: gives [n*(n-1)/2 n*(n-1)/2-1 ... n*(n-1)/2+1]
  ]      %   End if
  )      %   Index (1-based, modular) into the string. Gives a substring
         %   with the letters of one half of the parabola (***)
  Z?     %   Sparse: creates a char matrix with the substring (***) written
         %   at specified row (*) and column (**) positions. The remaining
         %   positions contain char(0), which will be displayed as space
]        % End do twice. We now have the two halves of the parabola, but
         % oriented horizontally instead of vertically
P        % Flip the second half of the parabola vertically, so that the
         % vertex matches in the two halves
v        % Concatenate the two halves vertically
1X!      % Rotate 90 degrees, so that the parabola is oriented vertically.
         % Implicitly display

```

# Answer
> 4 votes
# C, 184 bytes

```
i,j,k,l,m,h,o;f(n){char L[o=n*n][n*3];for(i=o;i--;)for(L[i][j=n*2]=h=k=0;j--;)L[i][j]=32;for(m=n;!h|~i;m-=1-h*2)for(h+(l=m)?++j:++h;l--;)L[h?i--:++i][j]=65+k++%26;for(;o--;)puts(L+o);}

```

Try it online!

**Unrolled:**

```
i, j, k, l, m, h, o;
f(n)
{
    char L[o=n*n][n*3];

    for (i=o; i--;)
        for (L[i][j=n*2]=h=k=0; j--;)
            L[i][j] = 32;

    for (m=n; !h|~i; m-=1-h*2)
        for (h+(l=m)?++j:++h; l--;)
            L[h?i--:++i][j] = 65 + k++%26;

    for (; o--;)
        puts(L+o);
}

```

# Answer
> 4 votes
# Java (OpenJDK 8), 121 bytes

```
n->{for(int l=n*++n/2,r=l,i=1,j=0;l>0;j=j-->0?j:i++)System.out.printf("%"+(n-i)+"c%"+(2*i-1)+"c%n",--l%26+65,r++%26+65);}

```

Try it online!

## Explanation

```
n->{                             // int-accepting consumer
 for(                            //  loop
   int l=n*++n/2,                //    declare l (left) is the first character to print.
                                 //              Oh, and n is increased to reduce byte count later.
       r=l,                      //            r (right) is the second character to print.
       i=1,                      //            i is the "outer-loop" index
       j=0;                      //            j is the "inner-loop" index
   l>0;                          //    while there are characters to print
   j=j-->0?j:i++)                //    simulate two loops in one,
                                 //      where j starts from 0 and always decreases until it reaches 0
                                 //      at which point j is reset to i and i is increased
  System.out.printf(             //   Print...
   "%"+(n-i)+"c%"+(2*i-1)+"c%n", //    2 characters
                                 //    - the first with n-i-1 whitespaces (remember, n was increased)
                                 //    - the second characters with 2*i-2 whitespaces
   --l%26+65,                    //    the first character to print is the left one, we decrease it.
   r++%26+65                     //    the second character to print is the right one, we increase it.
  );                             //
                                 //  end loop
}                                // end consumer

```

# Answer
> 3 votes
# Charcoal, ~~33~~ 31 bytes

```
≔⁰ηＦ…±Ｎ⊕θ«¿ι→↓Ｆ↔ι«Ｐ§αη≦⊕η¿›ι⁰↓↑

```

Try it online! Link is to verbose version of code. Edit: Saved 2 bytes thanks to @ASCII-only. Explanation:

```
≔⁰η

```

Initialise the current letter as an index into the uppercase alphabet to 0.

```
Ｆ…±Ｎ⊕θ«

```

Make a loop from the negation of the input to the input inclusive.

```
¿ι→↓

```

Normally each column is to the right of the previous. However, there is no column for zero. Instead, a correction is needed to ensure that the left and right sides align.

```
Ｆ↔ι«

```

Loop for each letter in the column.

```
Ｐ§αη

```

Print the current letter.

```
≦⊕η

```

Increment the letter index.

```
¿›ι⁰↓↑

```

Move up or down depending on which side of the trajectory we're on.

# Answer
> 3 votes
# Clojure, 417 319 bytes

```
(defn cannon[n](let[a(map #(char(+ 65 %))(iterate #(if(> % 24)0(inc %))0))m1(reverse(reduce #(concat %(repeat %2(- n %2)))[](range 0(inc n))))p1(map-indexed #(str(apply str(repeat %2 " "))(nth a %))m1)m2(reverse(reduce #(concat %(repeat %2(-(* 2 %2)2)))[](reverse(range 0(inc n)))))p2(reverse(map-indexed #(str(apply str (repeat %2 " "))(nth a(+(count p1)%)))m2))](doseq[x(reverse(map #(str % %2)p1 p2))](println x))))

```

At some point I got tangled up in `reverse` calls and gave up on the idea to make it as short as possible. I just wanted to have a working solution. Here you go...

### Sort of ungolfed

```
(defn cannon [n]
  (let [a (map #(char (+ 65 %)) (iterate #(if (> % 24) 0 (inc %)) 0))
        m1 (reverse (reduce #(concat % (repeat %2 (- n %2))) [] (range 0 (inc n))))
        p1 (map-indexed #(str (apply str (repeat %2 " ")) (nth a %)) m1)
        m2 (reverse (reduce #(concat % (repeat %2 (- (* 2 %2) 2))) [] (reverse (range 0 (inc n)))))
        p2 (reverse (map-indexed #(str (apply str (repeat %2 " ")) (nth a (+ (count p1) %))) m2))]
    (doseq [x (reverse (map #(str % %2) p1 p2))] (println x))))

```

## Update

Motivated by Olivier's comment, I managed to cut multiple `reverse` calls and apply some general golfing tricks to cut characters. Also I created aliases for `reverse`, `map-indexed`, `concat`, `repeat` and `str` because I used them multiple times each.

```
(defn c[n](let[a(map #(char(+ 65 %))(iterate #(if(> % 24)0(inc %))0))k #(reduce %[](range 0(inc n)))r #(apply str(repeat % " "))rv reverse m map-indexed c concat t repeat s str p(m #(s(r %2)(nth a %))(rv(k #(c %(t %2(- n %2))))))](rv(map #(s % %2)p(rv(m #(s(r %2)(nth a(+(count p)%)))(k #(c %(t %2(-(* 2 %2)2))))))))))

```

### Ungolfed

```
(defn c [n]
  (let [a (map
           #(char (+ 65 %))
           (iterate
            #(if (> % 24) 0 (inc %))
            0))
        k #(reduce
            %
            []
            (range 0 (inc n)))
        r #(apply str (repeat % " "))
        rv reverse
        m map-indexed
        c concat
        t repeat
        s str
        p (m
           #(s
             (r %2)
             (nth a %))
           (rv (k #(c % (t %2 (- n %2))))))]
    (rv
     (map
      #(s % %2)
      p
      (rv
       (m
        #(s
          (r %2)
          (nth a (+ (count p) %)))
        (k #(c % (t %2 (- (* 2 %2) 2))))))))))

```

Creates the function `c` which accepts the value n and returns a list of lines.

# Answer
> 3 votes
# Perl 5, -n ~~112~~ ~~92~~ ~~90~~ 88 bytes

For once the terribly long `printf` seems to win.

```
#!/usr/bin/perl -n
$p=$q=$_*($%=$_+1)/2;map{printf"%$%c%$.c
",--$p%26+65,$q++%26+65for--$%..$';$.+=2}//..$_

```

Try it online!

# Answer
> 2 votes
# Python3 + numpy, ~~124~~ 115

```
from pylab import*
def i(N):
 x=zeros((N,2*N),'U');x[r_[N-1:-1:-1,0:N],r_[:2*N]]=map(chr,r_[0:2*N]%26+65)
 return x

```

This creates an appropriately sized array, finds the indices for the trajectory and assigns the appropriate character to them. ~~The most complex part is generating the characters A-Z, which relies on a very hackish cast of numbers to a string type.~~ The returned object is a unicode array.

**Edit**: Saved 9 bytes replacing numpy code that generated the characters A-Z (`(r_[0:2*N]%26+65).view('U1')[::2]`) with `map`, as suggested here.

# Answer
> 2 votes
# Python 3, ~~139~~ 136 bytes

```
f=lambda n,o=0:n and'\n'.join([f(n-1,o+n).replace('\n','\n ')]+[chr(65+(n+o+~i)%26)+'  '*~-n+chr(65+(n*n+o+i)%26)for i in range(n)])or''

```

Try it online!

Generates each layer recursively, given the size and offset.

-3 bytes thanks to Jo King

# Answer
> 2 votes
# , <sup>~~78~~</sup> 75 bytes

```
(26{.65|.a.)($~#)`(;/@])`(' '$~1+{:@])}i.@+:(,.~(|.,])@i.@-:@#)@#~1+i.@-,i.

```

Try it online!

*-3 thanks to ngn*

# Answer
> 1 votes
# Python 2, 182 bytes

```
I=input()
S=list('ZYXWVUTSRQPONMLKJIHGFEDCBA'*I)
R=range
print zip(*[(' '*(sum(R(abs(i))))+eval('S.pop()+'*abs(i)+"''")[::[-1,1][i>0]]).ljust(sum(range(I+1)))for i in R(-I,I+1)if i])

```

Try it online!

Returns list of lists of chars. Primitive verification here

# Answer
> 1 votes
# Jelly, 35 bytes

```
ṪṚṭ
r1m0RØAṁs⁸U2¦Ç⁶ṁ$;¥\€ÇzZ¥€⁶ẎUZY

```

Try it online!

# Answer
> 1 votes
# Ruby, ~~106~~ 103 bytes

```
->n,f=2*s=-~n*n/2-1{l=*?A..?Z;(1..n).map{|i|i.times{puts' '*(n-i)+l[(f-s)%26]+' '*~-i*2+l[(s+=1)%26]}}}

```

Try it online!

# Answer
> 1 votes
# Yabasic, 125 bytes

An solution that uses graphics mode to print the characters at the correct column and row of the screen.

```
Input""n
Clear Screen
For i=-n To n
For j=1To Abs(i)
k=i>0
?@(i+n-k,(i^2-i)/2+j-2*j^(!k)+k)Chr$(c+65)
c=Mod(c+1,26)
Next
Next

```

Because this solution uses graphics mode, it cannot be executed on TIO.

### Output

*Below is the output for input `7`*

# Answer
> 1 votes
# QBasic 1.1, 124 bytes

Takes input and shoots a cannon. Due to screen size limitations, \\$n\\$ must be \\$\leq 6\\$.

```
INPUT n
CLS
FOR i=-n TO n
FOR j=1TO ABS(i)
k=i>0
LOCATE(i^2-i)/2+j-2*j^-(k=0)-k+1,i+n+k+1
?CHR$(c+65)
c=(c+1)MOD 26
NEXT j,i

```

# Answer
> 1 votes
# Python 3, 190 bytes

```
j,r,c,s=int(input()),range,[],[];a=(j+1)*j;b=a//2
for i in r(j):k=i+1;c.extend([j-k]*k)
for i in r(a):s+=chr(ord('A')+(i%26))
for i in r(b):print(' '*c[i]+s[b-i-1]+' '*(2*(j-c[i]-1))+s[b+i])

```

Try it online!

I tried my best. Let me know if any optimisations are possible.

# Answer
> 1 votes
# k4, ~~76~~ 71 bytes

```
{+|:'p$(-k,|k:+\l)$(x#b),|:'x_b:(i:-1_0,+\l,|l)_a:(2*p:+/l:|1+!x)#.Q.a}

```

some rearranging+assignments to save 5 bytes

---

```
{+|:'(+/l)$(-k,|k:+\l)$(x#i_a),|:'((-x)#i:-1_0,+\l,|l)_a:(2*+/l:|1+!x)#.Q.a}

```

half-hour effort with some effort to shave off a few bytes, but there's probably much more that can be done here. will come back to it. fun challenge!

---
Tags: code-golf, string, ascii-art, alphabet
---


title: Slowly converging zigzag

text:
# Question
Title: Slowly converging zigzag
Given a single positive odd integer as input, return a converging zigzag as a list of strings, list of lists of characters, or newline-separated string, in this form:

```
#
 #
  #
   #
    #
   #
  #
 #
  #
   #
  #

```

You can replace `#` with any consistent non-whitespace character. Trailing whitespace on each line is allowed and a trailing newline is allowed.

The zig-zag starts at column `1` and for each row moves right one column, until it reaches column `n` (where `n` is the input). Then, it moves left to `2`, then right to `n-1`, then left to `3`, with the two bounds converging in until the zigzag ends in the middle column (`(n+1)/2`).

# Test Cases

The example above is the test case for `5`.

The following are individual test cases:

```
3
#
 #
  #
 #

```

```
7
#
 #
  #
   #
    #
     #
      #
     #
    #
   #
  #
 #
  #
   #
    #
     #
    #
   #
  #
   #
    #
   #

```

```
1

#

```

# Answer
# C (gcc), 89 bytes

```
f(n,a,b){puts("0");for(a=n;--a>n/2;)for(b=n-2*a;b<=2*a-n;)printf(" %*d\n",a-abs(b++),0);}

```

Try it online!

Works by analyzing the sequence of number of spaces as (for n=7):

```
          0
1 2 3 4 5 6 5 4 3 2 1
    2 3 4 5 4 3 2
        3 4 3

```

And for n=3:

```
  0
1 2 1

```

We can see that the middle number (`a` in the code) runs from \[n-1, n/2). Then, the difference between the first number and the middle number is:

```
a  n  b  2a-n
-------------
6  7  5  5
5  7  3  3
4  7  1  1
2  3  1  1

```

So, if we have `b` going through \[-(2a-n), 2a-n\], `a-abs(b)` will give us the desired sequence. This is essentially what the code does.
> 15 votes

# Answer
# Charcoal, ~~10~~ 8 bytes

```
ＦＮ«↗ι‖»/

```

Try it online! Link is to verbose version of code. Edit: Saved 2 bytes thanks to @dzaima for pointing out that I don't have to use `#`s.
> 14 votes

# Answer
# Python 2, 78 bytes

```
l=range(1,input())
print 8
for i in l:
 for i in l:print' '*i+'8'
 l=l[-2::-1]

```

Try it online!
> 5 votes

# Answer
# Jelly, 14 bytes

```
ṖṖṚ$ÐĿẎ0;⁶ẋp1Y

```

Try it online!

Full program.

Uses `1`.

-1 thanks to Jonathan Allan.
-1 thanks to Jonathan Allan.
> 3 votes

# Answer
# Haskell, 72 bytes

```
g[]=[]
g a=a++g(reverse$init a)
r="#":map(' ':)r
("#":).g.tail.(`take`r)

```

Try it online!

We define an infinite list `r` being the diagonal of `#`s starting from the upper left hand corner.

We then define a function `g` which does the brunt of the work. `g` will take a list and repeatedly reverse it and remove its first element until the list is empty, then concatenate the result of each action.

Our main function here is a point-free function. This function starts by taking `n` elements from the infinite list `r`, it then chops of the first element and applies `g`. Last we have to add a `#` back to the beginning, this is because the specs for the question are a little weird, I'm not sure why the first diagonal is always one longer than it should be but, it is, so we have to add a a `#`.
> 3 votes

# Answer
# SOGL V0.12, 19 bytes

```
┘.»∫«I╝:±jk+jl0;±Iž

```

Try it Here!
> 2 votes

# Answer
# 05AB1E, 22 bytes

```
i8ë<LZFD¨R})˜0¸ìε8sú}»

```

Try it online!

Uses `8`.
> 2 votes

# Answer
# 05AB1E, 6 bytes

```
LN71SΛ

```

Try it online!

```
     Λ     use the canvas function with

L          a range list [1 .. input] as lengths for each path

 N         a "0" as character to be printed
           (N is the index variable used by loops. If there was no loop yet, its
           default value is 0. By using N, I avoid an extra space between 0 and 71)

  71S      and the directions 7 and 1 (NW and NE), that alternate automatically until
           the range list is finished.

```
> 2 votes

# Answer
# CJam, 29 bytes

```
ri,(;_,{_);W%}*]e_0\+Sf*8f+N*

```

Try it online!

Uses `8`.
> 1 votes

# Answer
## JavaScript, 127 bytes

Calculates the goal (`g`) to get to. When this goal is reached, turn around to the next goal. Also uses a trick to avoid using `Math.round()` by adding `0.5` to every uneven number.

```
f=n=>{c=0;for(i=0;i<n;i++){m=i/2;g=i%2==0?n-m:m+1.5;while(c!=g){c>g?c--:c++;console.log(' '.repeat(c-1)+'#'+' '.repeat(n-c))}}}

```

```
f=n=>{c=0;for(i=0;i<n;i++){m=i/2;g=i%2==0?n-m:m+1.5;while(c!=g){c>g?c--:c++;console.log(' '.repeat(c-1)+'#'+' '.repeat(n-c))}}}

f(5);
```
> 1 votes

# Answer
# Pyth, 23 bytes

```
8JStQKdVQjbm+*\ d8J=_PJ

```

Try it here.
> 1 votes

# Answer
## Haskell, 74 bytes

```
f[x]=[x]
f s=s++tail(f$reverse$tail s)
g n=f[(' '<$[2..x])++"#"|x<-[1..n]]

```

Try it online!

How it works:

```
    [(' '<$[2..x])++"#"|x<-[1..n]]     -- build the first diagonal, e.g. for n=3:
                                         -- ["#", " #", "  #"]
  f                                      -- call f, which is

f s = s ++                               -- the input list, followed by
           tail                          -- all but the first element of
                f                        -- a recursive call with
                  reverse                -- the reverse of
                          tail s         -- all but the first element of the input
                                         -- list
f[x]=[x]                                 -- base case: stop if the input list a
                                         -- singleton list

```

Each recursive call to `f` appends the next diagonal.
> 1 votes

# Answer
## Husk, 19 bytes

```
mo`:'#R' ∫`Ṙ¢e1_1tṫ

```

Try it online!

## Explanation

This feels a bit clunky.

```
mo`:'#R' ∫`Ṙ¢e1_1tṫ  Input is n (e.g. 5)
                  ṫ  Range from input to 1: [5,4,3,2,1]
                 t   Drop first element: [4,3,2,1]
             e1_1    The list [1,-1]
            ¢        repeated infinitely: [1,-1,1,-1,..
          `Ṙ         Clone with respect to the list above: [1,1,1,1,-1,-1,-1,1,1,-1]
         ∫           Cumulative sum: [0,1,2,3,4,3,2,1,2,3,2]
mo                   For each element k (e.g. 3) do this:
      R'             Repeat space k times: "   "
  `:'#               Append '#': "   #"
                     Print implicitly separated by linefeeds.

```
> 1 votes

# Answer
# Python 3, 82 bytes

```
def z(n):l=range(1,n);print(8);exec("[print(' '*i+'8')for i in l];l=l[-2::-1];"*n)

```

Try it online!
> 1 votes

# Answer
# Retina, 71 bytes

```
.+
$*
^
:>
 $
:
;{*T`:<>`_#
( ) >(:)|( )<
$1<$2$3
(:)( )<|>( )
$2$1$3>

```

Try it online! Explanation: The first three stages convert the input into the form `:> :` where the number of characters between the `:`s is the input number. The last two stages then bounce the `>` (or `<`, when moving leftward) between the `:`s. The fourth stage loops the bounce, printing the required parts of the string each time. The `;` stops the string from being printed after the loop.
> 1 votes

# Answer
# 05AB1E, 16 bytes

```
Î<L¤FÂ¦})˜Ôð×X«»

```

Try it online!

**Explanation**

```
Î<L               # push 0 and range [1 ... input-1]
   ¤              # get the last element of the list
    F             # that many times do
     Â            # bifurcate
      ¦           # remove the head
       })˜        # end loop and wrap in flattened list
          Ô       # remove consecutive duplicates
           ð×     # repeat space a number of times corresponding to each number in the list
             X«   # append 1 to each
               »  # join on newline

```
> 1 votes

# Answer
# K (Kona), 27 bytes

```
`0:{|x$"#"}'1,,/{1_|x}\-2-!

```

Produces the underlying numeric sequence by repeatedly reversing and dropping the head of a vector until empty.
> 1 votes

# Answer
# PHP, 65 bytes

```
<?while(--$n||$n=$d=--$argn)echo str_pad("X
",2+$x-=$d&1?:-1);?>X

```

Run as pipe with `-nF` or test it online.

**explanation:**

first iteration: `$n` is `NULL`, so `--$n` has no effect and evaluates to `NULL`
--\> set `$n` and `$d` to pre-decremented argument
1. increment `$x` for even `$d`, decrement for odd `$d`
2. print `X`, a newline and `$x` spaces

further iterations: decrement `$n`; when it hits `0`, reset `$n` (and `$d`) to pre-decremented argument

finale: print one more `X`.
> 0 votes

# Answer
# Japt, 31 bytes

```
Ç+V ç +QÃê ¯-2 c´U?ß´UVÄ :Vç +Q

```

Recursive solution that returns an array of lines.

Try it online! using the `-R` flag to join output with newlines.
> 0 votes

# Answer
# Mathematica, ~~142~~ 102 bytes (independent)

This solution has a mathy flavor:

`UnitVector[#,1-Sum[(-1)^Floor[#+1/2-Sqrt[9/4+#*#-#-2x]],{x,k}]]~Table~{k,0,#(#-1)/2}/.{0->" ",1->"X"}&`

This basically calculates which segment we're in (by inverting the triangular number function) and then moving left or right by adding a power of -1.

You can test it on the Wolfram Code Sandbox by pasting code like `UnitVector[#,1-Sum[(-1)^Floor[#+1/2-Sqrt[9/4+#*#-#-2x]],{x,k}]]~Table~{k,0,#(#-1)/2}/.{0->" ",1->"X"}&@6//MatrixForm` and pressing Shift+Enter or Numpad Enter or clicking Gear-\>"Evaluate Cell".

---

This happens to be the same length as my original incorrect port of Erik's Python 2 solution (This port gives the output for an input one higher):

`(Print[X];l=Range@#;Do[Do[Print[StringRepeat[" ",l[[j]]]<>"X"],{j,Length@l}];l=l[[-2;;1;;-1]],{i,#}])&`
> 0 votes

# Answer
# Python 2, ~~159~~ ~~145~~ ~~141~~ 136 bytes

```
print"".join([" "*p+"#\n"for p in(lambda l:[sum(l[:i])for i in range(len(l))])(sum([i*[1-i%2*2]for i in range(input())[::-1]],[])+[1])])

```

There has already been quite nice Python versions to this problem but I thought I'd still post my awful one-liner. (Without semicolons though!)

Edit: 14 bytes down, using sum instead of double list comprehension

Edit: Just noticed in python 2 you can use input instead of raw\_input. I've always just used the latter.
> 0 votes

---
Tags: code-golf, string, ascii-art
---


title: CUT OUT HEXAGONS

text:
# Question
Title: CUT OUT HEXAGONS
Write a full program or a function taking an unsigned integer number N and doing this cut out work:

* Cut out a hollow hexagon 'donut' shape with side B-C equal to 2N times '/'
* Translate the piece above by 3 lines.
* Repeat the job N times (from the piece obtained) decrementing by 2 '/' side B-C , until smallest hexagon (2 times '/').

This is the smallest hexagon which will be cut out last:

```
    side B-C     C____D
    is 2'/' ->   /    \
               B/      \
 side  C-D      \      /
is 4'_'          \____/
                A

```

Test cases:

N = 0 may output a blank sheet (nothing), but you don't heave to handle it.

N = 1:

```
  ____
 /    \
/      \
\      /
 \____/
/      \
\      /
 \____/

```

N = 3:

```
          ____
        _/    \_
      _//      \\_
     // \      / \\
    //   \____/   \\
   //   /______\   \\
  / \   \      /   / \
 /   \   \____/   /   \
/   / \          / \   \
\   \  \________/  /   /
 \   \            /   /
/ \   \          /   / \
\  \   \________/   /  /
 \  \              /  /
  \  \____________/  /
   \                /
    \              /
     \____________/

```

N = 8:

```
                              ____
                            _/    \_
                          _//      \\_
                        _// \      / \\_
                      _///   \____/   \\\_
                    _////   /______\   \\\\_
                  _//// \   \______/   / \\\\_
                _/////   \   \____/   /   \\\\\_
               //////   /_\          /_\   \\\\\\
              ///// \   \__\________/__/   / \\\\\
             /////   \   \____________/   /   \\\\\
            /////   / \   \          /   / \   \\\\\
           //// \   \  \   \________/   /  /   / \\\\
          ////   \   \  \              /  /   /   \\\\
         ////   / \   \  \____________/  /   / \   \\\\
        /// \   \  \   \                /   /  /   / \\\
       ///   \   \  \   \              /   /  /   /   \\\
      ///   / \   \  \   \____________/   /  /   / \   \\\
     // \   \  \   \  \                  /  /   /  /   / \\
    //   \   \  \   \  \________________/  /   /  /   /   \\
   //   / \   \  \   \                    /   /  /   / \   \\
  / \   \  \   \  \   \                  /   /  /   /  /   / \
 /   \   \  \   \  \   \________________/   /  /   /  /   /   \
/   / \   \  \   \  \                      /  /   /  /   / \   \
\   \  \   \  \   \  \____________________/  /   /  /   /  /   /
 \   \  \   \  \   \                        /   /  /   /  /   /
/ \   \  \   \  \   \                      /   /  /   /  /   / \
\  \   \  \   \  \   \____________________/   /  /   /  /   /  /
 \  \   \  \   \  \                          /  /   /  /   /  /
  \  \   \  \   \  \________________________/  /   /  /   /  /
   \  \   \  \   \                            /   /  /   /  /
    \  \   \  \   \                          /   /  /   /  /
     \  \   \  \   \________________________/   /  /   /  /
      \  \   \  \                              /  /   /  /
       \  \   \  \____________________________/  /   /  /
        \  \   \                                /   /  /
         \  \   \                              /   /  /
          \  \   \____________________________/   /  /
           \  \                                  /  /
            \  \________________________________/  /
             \                                    /
              \                                  /
               \________________________________/

```

Rules:
\- Margins are not specified.
\- Standard loopholes are forbidden.
\- Standard input/output methods.
\- Shortest answer in bytes wins.

Sandbox : https://codegolf.meta.stackexchange.com/a/18143/84844

# Answer
# Charcoal, 80 bytes

```
Ｆ⮌…·¹Ｎ«→↘Ｆ²«Ｍ⁺³×⁴ι↑Ｐ×_⊗ι↙Ｆ⊗ι«ＦκＰ× ⁴↙¹»→Ｆι«ＦκＰ× ⁴↘¹»Ｆ⊖ι«ＦκＰ× ⁻×³ιλ↘¹»\Ｐ×_⊗ι»»‖ＢＯ²

```

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

```
Ｆ⮌…·¹Ｎ«

```

Loop from the largest to the smallest hexagon.

```
→↘Ｆ²«Ｍ⁺³×⁴ι↑

```

Draw each hexagon twice in the desired location.

```
Ｐ×_⊗ι

```

Draw half of the top line of the hexagon.

```
↙Ｆ⊗ι«ＦκＰ× ⁴↙¹»

```

Draw the top left diagonal, but for each row erase 4 spaces first if this is the second hexagon.

```
→Ｆι«ＦκＰ× ⁴↘¹»

```

Draw half of the bottom left diagonal, still erasing 4 spaces first if this is the second hexagon.

```
Ｆ⊖ι«ＦκＰ× ⁻×³ιλ↘¹»

```

Draw almost all of the rest of the bottom left diagonal, erasing until the middle of the hexagon if this is the second hexagon.

```
\Ｐ×_⊗ι

```

Finish the bottom left diagonal and draw half of the bottom line of the hexagon.

```
»»‖ＢＯ²

```

Mirror everything at the end.

Alternative approach, also 80 bytes:

```
Ｆ⮌…·¹Ｎ«→↘Ｆ²«Ｍ⁺³×⁴ι↑ＦκＧ→⊗ι↓³←⊖⊗ι↙⊖⊗ι↘⊖⊗ι→⊖⊗ι↓³←⊗ι↖⊕⊗ι↗⊕⊗ι Ｐ×_⊗ι↙↙⊗ι→↘⊗ι↑Ｐ×_⊗ι»»‖Ｍ

```

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

```
Ｆ⮌…·¹Ｎ«

```

Loop from the largest to the smallest hexagon.

```
→↘Ｆ²«Ｍ⁺³×⁴ι↑

```

Draw each hexagon twice in the desired location.

```
ＦκＧ→⊗ι↓³←⊖⊗ι↙⊖⊗ι↘⊖⊗ι→⊖⊗ι↓³←⊗ι↖⊕⊗ι↗⊕⊗ι

```

Before drawing the second hexagon, erase the area between it and the next smaller hexagon.

```
Ｐ×_⊗ι↙↙⊗ι→↘⊗ι↑Ｐ×_⊗ι»»‖Ｍ

```

Draw the left half of each hexagon, and then mirror everything at the end.
> 4 votes

# Answer
# Canvas, ~~113~~ 112 bytes

```
«/＊α_×－／═↔⁸３＋ ＊－╶Ｒ⇵｛；Ｘ：«ｗ╷/###/＊Ｋｋｙ┤_×＋－ｙ#×/×－ｙ_×－／═ŗ∙ #⟳#¶#╋# ⟳_╋↔ｘ“kｙv╴e┌/ｉ┴⁰U＜ａlisｓfr↖；,ｉmＦE！↷qB╪²－‟＃ŗ｝#∙ ╋↔║

```

Try it here!

A part of the answer is literally evaluating the JavaScript `p.p.overlap(p.p,0,p.p,(a,b)=>b==0?a:b)`..
> 4 votes

# Answer
# C (clang), 374 bytes

```
#define F(X,R)*d=*(d=o+x*(l*3+35-g)+x/2+X+R)-32?*d:R?
i,z,x,l,w,r,g,m;f(n){int*d,o[i=z=(x=n*8+1)*(n*5+4)],*c=o;for(;l=i--;)*c++=i%x?32:10;for(;l++<n;)for(g=35;i=g-29;g-=3){for(r=m+=m=w=l*2;r--;F(~-w*x-w,r)g:g)F(w*~x,r)95:95,F(w*x-w,r)95:95;for(;w--;)for(r=4;r--;F(m-~w*~-x,-r)g:47)F(w-m-w*x,r)g:47,F(w-m-~w*x,r)g:92,F(m+~w-w*x,-r)g:92;}for(;i<z;++i)printf(o[i]-35?o+i:" ");}

```

Try it online!

-33 more saved by @ceilingcat improvement

# C (clang), ~~433~~ ~~412~~ 407 bytes

```
#define F(Y,X,W,R)*d=*(d=c-Y+X+W+R)-32?*d:R?
i,z,x,l,w,r,d,G,g,m;f(n){int*c,*d,o[i=z=(x=n*8+1)*(n*5+4)];for(c=o;l=i--;)*c++=i%x?32:10;for(;l++<n;)for(G=0;i=G<4;G+=3){g=35-G;c=o+x*l*3+G*x+x/2;for(r=m+=m=w=l*2;r--;F(x-w*x,-w,0,r)g:g)F(w*x,-w,0,r)95:95,F(-w*x,-w,0,r)95:95;for(;w--;)for(r=4;r--;F(~w*x,m,~w,-r)g:47)F(w*x,-m,w,r)g:47,F(~w*x,-m,w,r)g:92,F(w*x,m,~w,-r)g:92;}for(;i<z;)i+=printf(o[i]-35?o+i:" ");}

```

Try it online!

-21 thanks to @ceilingcat -5 @ceilingcat + y removed

```
   ###\
    ###\   <= we  draw only on spaces ' '
\###
 \###        first time we draw '#' for collisions

 /####\
/######\
\######/
 \####/

  ____
 /####\        then we move our drawing pointer
/######\     3 lines below
\######/
 \____/         and we draw spaces
/      \       instead of #
\      /
 \____/

      ____
    _/####\
   //######\     and we repeat for bigger donuts
  /#\######/   moving our drawing pointer
 /###\____/
/###/      \
\###\      /
 \###\____/
  \####??####/
   \________/

```
> 3 votes

---
Tags: code-golf, ascii-art
---


title: Diamondize Some Text

text:
# Question
Title: Diamondize Some Text
Given an input string of length `2` or longer consisting solely of alphabetical characters `[A-Z]` or `[a-z]` (your choice if they're all uppercase or all lowercase), output a continuous string of characters forming a double diamond pattern.

The input string starts on the center line and extends down-and-right at a diagonal until the end of the input string is reached. Then, the pattern continues up-and-right at a diagonal until you're as far above the center line as the length of the input string minus 1. Continue down-and-right back to the center line, then down-and-left, then up-and-left (going "behind" the center character), and finally down-and-left back to the starting character.

That's a little wordy, and it's better demonstrated by some examples:

```
"YOU"
  U   Y
 Y O U O
Y   O   U
 O Y U Y
  U   O

  ^   ^
 ↙ ↖ ↗ ↘
↘   ↗   >
 ↘ ↗ ↖ ↙
  V   V

```

See how the `YOU` starts at the center line and follows down-and-right, then up-and-right, etc., until it loops back to the beginning. Note especially how the `Y` on the up-and-left portion is "behind" the `O` and therefore not shown.

Some further examples:

```
"HI"
 I I
H H H
 I I

"TEST"
   E     E
  S T   T S
 T   T T   T
T     S     T
 E   E E   E
  S T   T S
   T     T

"HELLO"
    L       L
   O L     E L
  H   E   H   O
 E     H O     H
H       L       E
 E     L L     L
  L   E   L   L
   L H     E O
    O       H

```

---

* Input and output can be given by any convenient method.
* The input is guaranteed to be at least two letters long (i.e., you'll never receive `""` as input).
* You can print it to STDOUT or return it as a function result.
* Either a full program or a function are acceptable.
* Any amount of extraneous whitespace is acceptable, so long as the characters line up appropriately (e.g., feel free to pad as a rectangle).
* Standard loopholes are forbidden.
* This is so all usual golfing rules apply, and the shortest code (in bytes) wins.

# Answer
> 10 votes
# Charcoal, 17 bytes

```
ＧＨ<↗↘>↖↙ＬθθＧＨ<Ｌθθ

```

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

```
ＧＨ

```

Draw along a path.

```
<↗↘>↖↙

```

Draw in the directions ↘↗↗↘↙↖↖↙ (the `<` and `>` are shorthands for those two pairs, but the other pairs don't have shorthands.)

```
Ｌθ

```

Each path segment has the same length, including the ends, of the length of the input.

```
θ

```

Use the input as the text to be written along the path.

```
ＧＨ<Ｌθθ

```

Print the first two parts of the path again so that the middle character is correct.

# Answer
> 9 votes
# 05AB1E, 12 bytes

```
gIR7._•ÍÎ·•Λ

```

Try it online!

```
           Λ    use the canvas function
g               with the length of input for each segment
 IR7._          the input reversed and rotated left by 7 characters (we will draw this backwards to have the right center character)
      •ÍÎ·•     and the directions 1, 3, 3, 1, 7, 5, 5, 7 as a compressed number.

```

# Answer
> 7 votes
# JavaScript (ES6),  ~~157 155~~  154 bytes

Returns a matrix of characters.

```
s=>(y=n=s.length,y+=i=X=Y=-1,m=[...Array(y+n)].map(_=>r=Array(4*n-3).fill` `),g=x=>x?g(x-=r[m[y][++i==6*n-6||+x]=s[i%n],y-=m[y-Y]?Y:Y=-Y,x-X]?X:X=-X):m)``

```

Try it online!

### How?

Given the length \\$n\\$ of the input string, we build a matrix of size \\$w\times h\\$, with:

* \\$w = 4n-3\\$
* \\$h = 2n-1\\$

We run a simulation of a 'ball' bouncing in this matrix, starting at \\$(0,n-1)\\$ and heading South-East, until it's back to its initial position.

The 0-based index of the center character that must be skipped in the diamond shape is:

$$p=6n-6$$

Example for \\$n=4\\$:

### Commented

```
s => (                           // s = input string
  y = n = s.length,              // n = length of s
  y += i = X = Y = -1,           // y = n - 1; i = X = Y = -1
  m =                            // create a matrix m[]:
    [...Array(y + n)].map(_ =>   //   - of height 2n-1
      r = Array(4 * n - 3)       //   - of width 4n-3 (save one of these rows in r[])
          .fill` `               //   - initially filled with spaces
    ),                           //
    g = x =>                     // g is a recursive function taking x
      x ?                        //   if x is truthy:
        g(                       //     do a recursive call:
          x -= r[                //       update x:
            m[y][                //         update m[y][x]:
              ++i == 6 * n - 6   //           unless this is the 2nd pass through the
              || +x              //           center cell, set it to the next character
            ] = s[i % n],        //           in s (otherwise we write to m[y][true]
                                 //           instead, which has no effect)
            y -=                 //         update y:
              m[y - Y] ? Y       //           bounce vertically if m[y - Y] is undefined
                       : Y = -Y, //
            x - X                //         bounce horizontally
          ] ? X                  //         if r[x - X] is undefined
            : X = -X             //
        )                        //     end of recursive call
      :                          //   else:
        m                        //     stop recursion and return m[]
)``                              // initial call to g with x = [''] (zero-ish but truthy)

```

# Answer
> 3 votes
# , ~~79~~ ~~77~~ 75 bytes

```
(|.@$~8*])`([:;/(1,~<:@])+/\@,(_2{&1 _1\#:33495)}.@#~])`(' '$~1+2 4*])}<:@#

```

Try it online!

# Answer
> 3 votes
## JavaScript (ES6), 136 bytes

```
f=
(s,l=s.length-1,z=l*4,a=[...Array(l-~l)].map(_=>Array(z+1).fill` `),g=x=>x--?g(x,a[a[y=(x+l)%z]?y:z-y][x>z?z+z-x:x]=s[x%-~l]):a)=>g(z+z)
```

```
<input oninput=o.textContent=f(this.value).map(c=>c.join``).join`\n`><pre id=o>
```

Returns a two-dimensional array. Works by drawing the string into the array directly computing the destination co-ordinates working backwards from the end so that the centre cell is overwritten automatically. Explanation:

```
(s

```

Input string.

```
,l=s.length-1

```

Distance between "bounces", also half the last row index and one less than the length.

```
,z=l*4

```

Last column index, also half of the length of text to draw.

```
,a=[...Array(l-~l)].map(_=>Array(z+1).fill` `)

```

Array of spaces.

```
,g=x=>x--

```

Count down from the last cell to the first.

```
  ?g(x

```

Recursive call to process the remaining cells.

```
    ,a[a[y=(x+l)%z]?y:z-y]

```

Calculate the row of this cell.

```
      [x>z?z+z-x:x]=s[x%-~l])

```

Calculate the column of this cell and the character that belongs there.

```
  :a

```

Finish by returning the array.

```
)=>g(z+z)

```

Start at the end of the text.

# Answer
> 1 votes
# C (clang), ~~201~~ ~~196~~ 188 bytes

```
x,y,i,v,m,n;f(s,z){char*a=s,o[i=(y=z*2-1)*(x=y+y)];for(v=x*2-2;i;n=m=1)o[--i]=i%x?32:10;for(i=x*--z;v--;i+=x*m+n)o[i]==32?o[i]=*a:0,a=*++a?a:s,n=i%x>x-3?-1:n,m=i/x?i/x<y-1?m:-1:1;puts(o);}

```

Try it online!

-13 @ceilingcat suggestions

# Answer
> 0 votes
# Python 2, 137 bytes

```
s=input();n=len(s);m=2*n-2
for r in range(m+1):print''.join([s[[x,-8-x][(x<=m)==(m>2*r)]%n],' '][r!=(x+1-n)%m!=m-r]for x in range(4*n-3))

```

Try it online!

A full program that takes a string as input as prints out the diamondized version.

---
Tags: code-golf, string, ascii-art
---


title: The Celestial Bureaucracy KoTH

text:
# Question
Title: The Celestial Bureaucracy KoTH
In Imperial China, ranks in society were not decided by birth or wealth, but by a person's ability to excel in the Imperial Examinations. The Jade Emperor, divine ruler of the Heavens, has called for all his subjects to be examined to determine their worth, and whom to next give the Divine Mandate to rule China.

## Rules of the Bureaucracy:

* The Divine Bureaucracy consists of non-negative integer-valued ranks, starting with 0. Each member (bot) of the bureaucracy belongs to one rank. Each rank can hold arbitrary many members, but can't be empty unless all ranks above are empty
* At the start of the game, all members have rank 0
* Every turn, each member of the bureaucracy has to answer an exam. The exam consist of correctly guessing the boolean values of a list. The length of the list is the number of the rank above the member.
* The exam questions are prepared by a random member of the rank above. Members of the highest rank get their questions directly from the `JadeEmperor` (see below)
* A member scoring at least 50% on their exam is eligible for Promotion. A member scoring less than 50% on their exam is eligible for Demotion.
* A member eligible for Demotion has their rank decreased by one only if there is a member eligible for Promotion on the rank below to take their place.
* All members eligible for Promotion have their rank increased by one as long as this leaves no rank empty.
* If not all eligible members can be Demoted or Promoted, the preference goes to those of lowest (for Demotion) resp. highest (for Promotion) score. Ties are broken randomly.
* The rank of a member can only change by at most 1 each turn.

## Rules of the game:

* Each bot will be randomly assigned an ID at the start of the game, which will not change over its course. The `JadeEmperor` has the ID -1, all others have consecutive non-negative IDs, starting with 0.
* All bots compete at the same time
* The game runs for 100 turns, the score of the bot is its average rank possessed over that time.
* Total score is acquired by running 1000 games and averaging the results.
* Each Bot is a **Python 3** class implementing the following four functions:
    + `ask(self,n,ID)`, which makes an exam by returning a `list` of Booleans of length n. ID is the ID of the bot who has to guess that list. `ask()` can be called many times during a single round for any bot, but also not at all.
    + `answer(self,n,ID)`, which is an attempt to answer an exam by returning a `list` of Booleans of length n. ID is the ID of the bot whose `ask()` generated the exam. `answer()` is called exactly once per round for each bot.
    + `update(self,rankList,ownExam,otherExams)` is called once the Controller has performed all Pro- and Demotions. Its arguments are: A list of integers, listing all ranks by ID of all bots; a tuple, consisting of two lists, first the exam questions, then the answers the bot gave (in case it forgot); then a list of tuples, similarly consisting of exam-answer pairs, this time for all exams the bot handed out.
    + `__init__(self, ID, n)` passes the bot its own ID and the number of competing bots.
* Classes are allowed to implement other functions for private use
* Defining further variables and using them to store data about past exams is explicitly allowed.
* Programming meta-effects are forbidden, meaning any attempts to directly access other bots' code, the Controller's code, causing Exceptions or similar. This is a contest of strategies for the exams, not of code hacking.
* Bots trying to help each other are explicitly allowed, as long as they don't do it via meta-effects, but purely by the information passed through `update()`
* Other languages are allowed only in case they can be easily converted to Python 3.
* The library numpy will be imported as `np`. The version is 1.6.5, meaning it uses the old random library. If you have numpy 1.7, the old functions are available under `numpy.random.mtrand` for testing. Please remember to strip the mtrand for submission.
* If a bot causes an Exception during runtime, it is disqualified. Any bot whose code is so obfuscated that it's impossible to tell if it generates a list of length n when `ask()` or `answer()` is called will also be disqualified preemptively. A bot forcing me to deep-copy outputs gets -1 on the score.
* Class names have to be unique
* Multiple bots per person are allowed, but only the latest version will be taken of iteratively updated bots.
* Since there seems to be some confusion about bot similarity:
    + You are **not allowed** to post a copy of another bot. This is the only Standard Loophole which really applies in this challenge.
    + You are **allowed** to have shared code with other bots, including bots of other people.
    + You are **not allowed** to submit a bot which differs from another only by a trivial change to the strategy (like a change in the seed for the question generation) **unless** you can prove that the number of such carbon copy bots is the minimum required for successful enactment of their strategy (That will usually be two bots for a cooperation).

### Example Bots:

The `JadeEmperor` is always part of the game, but does not compete; he serves as generator for exams of highest-rank bots. His exams are random, but not uniformly, to allow smart bots a way to advance.

```
class JadeEmperor:
    def __init__(self):
        pass

    def ask(self,n,ID):
        num=min(np.random.exponential(scale=np.sqrt(np.power(2,n))),np.power(2,n)-1)
        bi=list(np.binary_repr(int(num),width=n))
        return [x=='0' for x in bi]

```

The **Drunkard** produces exams and answers completely randomly. He will be part of the game.

```
class Drunkard:
    def __init__(self,ID,n):
        pass

    def ask(self,n,ID):
        return list(np.random.choice([True,False],size=n,replace=True))

    def answer(self,n,ID):
        return list(np.random.choice([True,False],size=n,replace=True))

    def update(self,rankList,ownExam,otherExams):
        pass #out

```

The **Plagiarist** just copies previous exams. He will also be part of the game.

```
class Plagiarist:
    def __init__(self,ID,n):
        self.exam=[True]

    def ask(self,n,ID):
        return (self.exam*n)[0:n]

    def answer(self,n,ID):
        return (self.exam*n)[0:n]

    def update(self,rankList,ownExam,otherExams):
        self.exam=ownExam[0]

```

Controller code available here. For testing, you can put your own class into a Contestants.py file in the same folder, and they will be imported.

Chatroom can be found here.

# The Examinations begin!

Current score, in higher precision (10000 runs) for Oct20:

$$ \begin{array}{|c|c|c|}\hline \textbf{Entrant}&\textbf{Author}&\textbf{Score}\\\hline % \text{Alpha}&\text{Sleafar}&9.669691\\ \hline \text{Gamma}&\text{Sleafar}&9.301362\\ \hline \text{Beta}&\text{Sleafar}&9.164597\\ \hline \text{WiQeLu}&\text{Purple P}&7.870821\\ \hline \text{StudiousBot}&\text{Dignissimus - Spammy}&7.538537\\ \hline \text{Santayana}&\text{Sara J}&7.095528\\ \hline \text{Plagiarist}&\text{}&6.522047\\ \hline \text{CountOracular}&\text{IFcoltransG}&5.881175\\ \hline \text{Thomas}&\text{Alien@System}&5.880041\\ \hline \text{Contrary}&\text{Draco18s}&5.529652\\ \hline \text{Marx}&\text{sugarfi}&5.433808\\ \hline \text{Drunkard}&\text{}&5.328178\\ \hline \text{YinYang}&\text{Purple P}&5.102519\\ \hline \text{Equalizer}&\text{Mnemonic}&4.820996\\ \hline \text{TitForTat}&\text{Anonymous}&3.35801\\ \hline \end{array}$$

Contests will be run with each new entry for the foreseeable future.

# Answer
# Santayana

Those who cannot remember the past are condemned to repeat it. So we make our decisions based on how the others have acted in the past, answering based on what answer the asker has usually expected from us at a given index, and asking for the answer they've given us the least often at a given index.

```
import numpy as np

class Santayana:
    """
    Those who cannot remember the past are condemned to repeat it
    """
    def __init__(self, ID, num_competitors):
        self.ID = ID
        self.exams_taken = {}
        self.exams_issued = {}
        self.last_exam_asker = None
        self.recent_exam_takers = []

        for i in range(num_competitors):
            self.exams_taken[i] = []
            self.exams_issued[i] = []

    def ask(self, length, taker_ID):
        # Remember who asked
        self.recent_exam_takers.append(taker_ID)
        new_exam = []

        # At every index, expect the answer they've given the least often (default to False if equal)
        for i in range(length):
            trues = 0
            falses = 0
            for exam in self.exams_issued[taker_ID]:
                if len(exam) <= i: continue
                if exam[i]:
                    trues += 1
                else:
                    falses += 1
            new_exam.append(trues < falses)
        return new_exam

    def answer(self, num_answers, asker_ID):
        self.last_exam_asker = asker_ID
        if asker_ID == -1:
            # Copy emperor's process to hopefully get a similar exam
            num = min(np.random.exponential(scale=np.sqrt(np.power(2,num_answers))),np.power(2,num_answers)-1)
            as_bin = list(np.binary_repr(int(num),width=num_answers))
            return [x=='0' for x in as_bin]
        else:
            new_answer = []

            # At every index, give the answer that's been correct the greatest number of times (default to True if equal)
            for i in range(num_answers):
                trues = 0;
                falses = 0;
                for exam in self.exams_taken[asker_ID]:
                    if len(exam) <= i: continue
                    if exam[i]:
                        trues += 1
                    else:
                        falses += 1
                new_answer.append(trues >= falses)
            return new_answer

        return [True for i in range(num_answers)]

    def update(self, rank_list, own_exam, other_exams):
        if self.last_exam_asker > -1:
            # Save the exam we took, unless it was from the Emperor - we already know how he operates
            self.exams_taken[self.last_exam_asker].append(own_exam[0])
        for i in range(len(self.recent_exam_takers)):
            # Save the responses we got
            self.exams_issued[i].append(other_exams[i][1])

        self.recent_exam_takers = []

```
> 4 votes

# Answer
# Alpha

*Read the chat before downvoting. These bots don't violate any rules. The OP is even encouraging cooperating bots.*

Alpha is forming a team together with Beta. Both are using a predefined set of exams to help each other rise up the ranks. Also both are taking advantage of bots using the same exams over and over.

```
import numpy as np
import hashlib

class Alpha:
    def __init__(self, ID, n):
        self.alpha = hashlib.md5(b"Alpha")
        self.beta = hashlib.md5(b"Beta")
        self.asker = -1
        self.betas = set(range(n)).difference([ID])
        self.fixed = set(range(n)).difference([ID])
        self.fixedExams = [[]] * n

    def ask(self,n,ID):
        if ID in self.betas:
            return self.md5ToExam(self.alpha, n)
        else:
            return list(np.random.choice([True, False], n))

    def answer(self,n,ID):
        self.asker = ID
        if self.asker == -1:
            return [True] * n
        elif self.asker in self.fixed and len(self.fixedExams[self.asker]) > 0:
            return (self.fixedExams[self.asker] * n)[:n]
        elif self.asker in self.betas:
            return self.md5ToExam(self.beta, n)
        else:
            return list(np.random.choice([True, False], n))

    def update(self,rankList,ownExam,otherExams):
        if self.asker >= 0:
            if self.asker in self.betas and ownExam[0] != self.md5ToExam(self.beta, len(ownExam[0])):
                    self.betas.remove(self.asker)
            if self.asker in self.fixed:
                l = min(len(ownExam[0]), len(self.fixedExams[self.asker]))
                if ownExam[0][:l] != self.fixedExams[self.asker][:l]:
                    self.fixed.remove(self.asker)
                    self.fixedExams[self.asker] = []
                elif len(ownExam[0]) > len(self.fixedExams[self.asker]):
                    self.fixedExams[self.asker] = ownExam[0]
        self.alpha.update(b"Alpha")
        self.beta.update(b"Beta")

    def md5ToExam(self, md5, n):
        return [x == "0" for x in bin(int(md5.hexdigest(), 16))[2:].zfill(128)][:n]

```
> 3 votes

# Answer
# Studious Bot

This bot studies for tests! It attempts to find patterns in tests given out by various bots and acts accordlingly.

On my end, so far, this bot outperforms all other bots that I could get working on my computer except from Alpha, Beta and Gamma (who have been programmed to work together). The bot doesn't make use of the fact that teaming is allowed because I felt that it was a bit like cheating and slightly dirty. Looking over it though, teaming seems to seems to be quite effective.

The bot attempts to recognise when the answers to tests are random and in response matches that to hopefully average 50% on tests.

The bot also attempts to recognise when a bot has merely flipped its answers to throw off other bots who are tying to predict their behaviour, however I haven't programmed it to specifically act on this yet.

I've annotated the code with a few comments in order to make it easier to read

```
import random
import numpy as np

class StudiousBot:
    GRAM_SIZE = 5
    def __init__(self, identifier, n):
        self.id = identifier
        self.ranks = {i: 0 for i in range(n)} # Stores ranks
        self.study_material = {i: [] for i in range(n)} # Stores previous exam data
        self.distribution = {i: [] for i in range(n)} # Stores the percentage of answers that were `True` on a Bot's tests over time
        self.last_examiner = None

    def ask(self, n, identifier):
        # This bot gives random tests, it doesn't bother making them difficult based on answers to them
        # The reason for this is that I can't personalise the tests for each bot
        return [random.choice([True, False]) for i in range(n)]

    def answer(self, n, examiner_id):
        self.last_examiner = examiner_id
        if examiner_id == -1:
            return StudiousBot.answer_emperor(n) # Easy win, I know the distribution of answers for the Emperor's tests

        bother_predicting = True # Whether or not the Bot will attempt to predict the answers to the exam
        study_material = self.study_material[examiner_id]
        distribution = self.distribution[examiner_id]
        if len(distribution) > 0: # If there is actually data to analyse
            sd = StudiousBot.calculate_standard_deviation(distribution)
            normalised_sd = StudiousBot.calculate_normalised_standard_deviation(distribution)

            if abs(30 - sd) < 4: # 30 is the expected s.d for a random distribution
                bother_predicting = False # So I won't bother predicting the test

            if abs(sd - normalised_sd * 2) > 4: # The bot is merely inverting answers to evade being predicted
                pass # However, at this time, I'm not certain how I should deal with this. I'll continue to attempt to predict the test

        if bother_predicting and len(study_material) >= StudiousBot.GRAM_SIZE:
            return StudiousBot.predict(study_material, n)

        return [random.choice([True, False]) for i in range(n)]

    def predict(study_material, n): # Predicts the answers to tests with `n` questions
        grams = StudiousBot.generate_ngrams(study_material, StudiousBot.GRAM_SIZE) # Generate all n-grams for the study material
        last_few = study_material[-(StudiousBot.GRAM_SIZE - 1):] # Get the last 9 test answers
        prediction = None
        probability = -1
        for answer in [True, False]: # Finds the probabiility of the next answer being True or False, picks the one with the highest probability
            new_prediction = last_few + [answer]
            new_probability = grams.count(new_prediction)

            if new_probability > probability:
                prediction = answer
                probability = new_probability

        if n == 1:
            return [prediction]

        return [prediction] + StudiousBot.predict(study_material + [prediction], n-1)

    @staticmethod
    def calculate_standard_deviation(distribution):
        return np.std(distribution)

    def calculate_normalised_standard_deviation(distribution): # If the answers happen to be inverted at some point, this function will return the same value for answers that occured both before and after this point
        distribution = list(map(lambda x: 50 + abs(50-x), distribution))
        return StudiousBot.calculate_standard_deviation(distribution)

    @staticmethod
    def generate_ngrams(study_material, n):
        assert len(study_material) >= n
        ngrams = []
        for i in range(len(study_material) - n + 1):
            ngrams.append(study_material[i:i+n])

        return ngrams

    def update(self, ranks, own_exam, other_exams):
        self.ranks = dict(enumerate(ranks))
        if self.last_examiner != -1:
            self.study_material[self.last_examiner] += own_exam[0]
            self.distribution[self.last_examiner].append(own_exam[0].count(True) / len(own_exam[0]) * 100) # Stores the percentage of the answers which were True

    @staticmethod
    def answer_emperor(n): # Algorithm to reproduce Emperor's distribution of test answers
        exp = np.random.exponential(scale=np.sqrt(np.power(2,n)))
        power = np.power(2,n) - 1
        num = min(exp, power)
        bi = list(np.binary_repr(int(num), width=n))
        return [x == '0' for x in bi]

```
> 3 votes

# Answer
# Count Oracular

This bot uses an algorithm that averages the exams of all other working bots, (given the round number and some terrible heuristics) for deciding what each other bot will set as the exam.
The Count asks its exams using an md5 hash. Both its questions and its answers are therefore deterministic. It ignores most inputs, asking and answering the exact same sequences of booleans, rain or shine, including against Jade Emporer.

```
import numpy as np
import hashlib

class CountOracular:
    '''Uses very little external data to make heuristical statistical
    deterministic predictions about the average exam.
    (Assonance not intended.)
    To generate its own exams, uses a deterministic hash.'''
    def __init__(self, id, number_of_bots):
        self.last_round = []
        #functions for calculating what other bots will likely do.
        self.bots_calculators = [
            self._jad, #Jade Emporer
            self._alp, #Alpha
            self._bet, #Beta
            self._gam, #Gamma
            self._wiq, #Wi Qe Lu
            self._stu, #StudiousBot
            self._pla, #Plagiarist
            self._san, #Santayana
            self._tho, #Thomas
            self._dru, #Drunkard
            self._yin, #YinYang
            self._con, #Contrary
            self._tit, #TitForTat
            self._equ, #Equalizer
            self._mar, #Marx
        ]
        self.bot_types = len(self.bots_calculators)
    def ask(self, n, id):
        #if we can, show that hardcoding is no match for the power of heuristics:
        if n == 2:
            return [False, True]
        #otherwise, refer to the wisdom of Mayor Prentiss in order to command The Ask
        #i.e. hashes a quote, and uses that as the exam.
        salt = b"I AM THE CIRCLE AND THE CIRCLE IS ME " * n
        return self._md5_from(salt, n)
    def answer(self, n, id):
        #uses the power of heuristics to predict what the average bot will do
        #ignores all inputs except the length of the output
        #very approximate, and deterministic
        #i.e. every game, Count Oracular will send the same lists of answers, in the same order
        best_guess_totals = [0.5] * n #halfway between T and F
        for bot in self.bots_calculators:
            exam, confidence = bot(n)
            if not exam:
                continue
            while len(exam) < n:
                #ensure exam is long enough
                exam += exam[:1]
            exam = exam[:n] #ensure exam is short enough
            #map T and F to floats [0,1] based on confidence
            weighted_exam = [0.5+confidence*(0.5 if q else -0.5) for q in exam]
            best_guess_totals = [current+new for current,new in zip(best_guess_totals, weighted_exam)]
        best_guess_averages = [total/self.bot_types
            for total
            in best_guess_totals
        ]
        best_guess = [avg > 0.5 for avg in best_guess_averages]
        self.last_round = best_guess
        return best_guess
    def update(self, ranks, own, others):
        pass
    def _md5_from(self, data, n):
        md5 = hashlib.md5(data)
        for i in range(n):
            md5.update(data)
        exam = []
        while len(exam) < n:
            exam += [x == "0"
                for x
                in bin(int(md5.hexdigest(), 16))[2:].zfill(128)
            ]
            md5.update(data)
        return exam[:n]
    def _invert(self, exam):
        return [not val for val in exam]
    def _digits_to_bools(self, iterable):
        return [char=="1" for char in iterable]
    def _plagiarise(self, n):
        copy = (self.last_round * n)[:n]
        return copy

    '''functions to calculate expected exams for each other bot:
       (these values, weighted with corresponding confidence ratings,
       are summed to calculate the most likely exam.)'''
    def _jad(self, n):
        '''Calculate the mean of _jad's distribution, then
        use that as the guess'''
        mean = max(int(np.sqrt(np.power(2,n))), (2<<n)-1)
        string_mean = f"{mean}".zfill(n)
        exam = self._invert(self._digits_to_bools(string_mean))
        return exam, 0.5
    def _alp(self, n):
        '''Alpha uses a predictable hash,
        until it figures out we aren't Beta,
        modelled by the probability of giving or solving
        Alpha's exam'''
        #probability that Alpha thinks we're Beta
        #assuming we fail to pretend to be Beta if we meet Alpha
        chance_beta = ((1 - 1/self.bot_types) ** n) ** 2
        return self._md5_from(b"Beta", n), chance_beta
    def _gam(self, n):
        '''Gamma is like Beta, except after realising,
        switches to 50-50 random choice of inverse
        either Beta or Alpha's hash'''
        #probability that Gamma thinks we're Alpha still
        #(Unlikely that Gamma will think we're Beta;
        #we'd need to fail Alpha but pass Beta,
        #therefore, not accounted for)
        chance_unknown = ((1 - 1/self.bot_types) ** n) ** 2
        #default exam that assumes that Gamma thinks we're Alpha
        exam = self._md5_from(b"Beta", n)
        if chance_unknown > 0.5:#there exists a better heuristic here
            #assume Gamma will consider us Alpha
            confidence = chance_unknown
        else:
            #assume Gamma considers us neither Alpha nor Beta
            alpha = self._invert(self._md5_from(b"Beta", n))
            beta = self._invert(self._md5_from(b"Alpha", n))
            #check for bools where both possible exams match
            and_comp = [a and b for a, b in zip(alpha, beta)]
            nor_comp = [not (a or b) for a, b in zip(alpha, beta)]
            #count up matches vs times when fell back on default
            #to calculate ratio of default
            #to bools where hashes agree
            confidence_vs_default = (sum(and_comp)+sum(nor_comp)) / n
            confidence = confidence_vs_default * chance_unknown + (1 - confidence_vs_default) * (1 - chance_unknown)
            for i in range(n):
                if and_comp[i]:
                    exam[i] = True
                if nor_comp[i]:
                    exam[i] = False
        return exam, confidence
    def _bet(self, n):
        '''Beta is like Alpha, but with a different hash'''
        #probability we haven't matched with Beta yet
        #i.e. probability that Beta still thinks we're Alpha
        chance_alpha = ((1 - 1/self.bot_types) ** n) ** 2
        return self._md5_from(b"Alpha", n), chance_alpha
    def _wiq(self, n):
        '''Wi Qe Lu is hard to model, so we pretend
        that it mimicks Plagiarist for the most part'''
        if n == 1:
            #first round is random
            return [False], 0
        #other rounds are based on exams it met
        #leaning towards same as the previous exam
        return self._plagiarise(n), 0.1
    def _stu(self, n):
        '''StudiousBot is random'''
        return [False] * n, 0
    def _pla(self, n):
        '''Plagiarist copies the exams it received,
        which can be modelled with the standard prediction
        calculated for the previous round, padded with its first
        element.'''
        if n == 1:
            return [True], 1
        return self._plagiarise(n), 0.3
    def _san(self, n):
        '''Santayana is based on answers, which we don't predict.
        Modelled as random.'''
        #mostly random, slight leaning towards default False
        return [False] * n, 0.1
    def _tho(self, n):
        '''Thomas has an unpredictable threshold.'''
        #for all intents, random
        return [False] * n, 0
    def _dru(self, n):
        '''Drunkard is utterly random.'''
        return [False] * n, 0
    def _yin(self, n):
        '''YinYang inverts itself randomly, but not unpredictably.
        We can model it to find the probability. Also notably,
        one index is inverted, which factors into the confidence
        especially for lower n.'''
        if n == 1:
            #one element is inverted, so whole list must be False
            return [False], 1
        if n == 2:
            #split half and half randomly; can't predict
            return [True] * n, 0
        #cumulative chance of mostly ones or mostly zeros
        truthy = 1
        for _ in range(n):
            #simulate repeated flipping
            truthy = truthy * 0.44 + (1-truthy) * 0.56
        falsey = 1 - truthy
        if falsey > truthy:
            return [False] * n, falsey - 1/n
        return [True] * n, truthy - 1/n
    def _con(self, n):
        '''Contrary is like Jade Emporer, but inverts itself
        so much that modelling the probability of inversion
        is not worth the effort.'''
        #there are some clever ways you could do statistics on this,
        #but I'm content to call it uniform for now
        return [False] * n, 0
    def _tit(self, n):
        '''TitForTat is most likely to give us False
        but the confidence drops as the chance of having
        met TitForTat increases.
        The square root of the probability we calculate for
        Alpha, Beta and Gamma, because those also care about what
        we answer, whereas TitForTat only cares about what we ask'''
        #probability that we've not given TitForTat an exam
        chance_friends = (1 - 1/self.bot_types) ** n
        return [False] * n, chance_friends
    def _equ(self, n):
        '''Equalizer always asks True'''
        #certain that Equalizer's exam is all True
        return [True] * n, 1
    def _mar(self, n):
        '''Marx returns mostly True, randomised based on our rank.
        We don't predict our rank.
        There's ~50% chance an answer is random'''
        #75% chance we guess right (= 50% + 50%*50%)
        return [True] * n, 0.75

```
> 3 votes

# Answer
# YinYang

Answers either all `True` or all `False`, except for one index randomly chosen to be the opposite. Asks the opposite of what it answers. Swaps randomly to throw off opponents.

```
import random

class YinYang:
    def __init__(self, ID, n):
        self.exam = True

    def update(self, rankList, ownExam, otherExams):
        if random.random() < 0.56:
            self.exam = not self.exam

    def answer(self, n, ID):
        a = [not self.exam] * n
        a[random.randint(0, n-1)] = self.exam
        return a

    def ask(self, n, ID):
        e = [self.exam] * n
        e[random.randint(0, n-1)] = not self.exam
        return e

```

# Wi Qe Lu (Switcheroo)

Answers and asks randomly in the first round. Afterwards, he uses the answers from the previous exam, and changes a question if an above-average number of competitors got it right.

```
class WiQeLu:
    def __init__(self, ID, n):
        self.rounds = 1
        self.firstexam = True
        self.firstanswer = True
        self.lastexaminer = -1
        self.exam = []
        self.pastanswers = {}

    def update(self, rankList, ownExam, otherExams):
        questions, lastanswers = ownExam
        self.pastanswers[self.lastexaminer] = questions

        if len(otherExams) == 0:
            return
        correctCounts = [0 for i in otherExams[0][0]]
        for ourExam, response in otherExams:
            for i in range(len(response)):
                if ourExam[i] == response[i]:
                    correctCounts[i] += 1

        newExam = otherExams[0][0]
        meanWhoAnsweredCorrectly = sum(correctCounts) / len(correctCounts)
        for i in range(len(correctCounts)):
            if correctCounts[i] > meanWhoAnsweredCorrectly:
                newExam[i] = not newExam[i]
        self.exam = newExam

    def answer(self, n, ID):
        self.lastexaminer = ID
        if ID not in self.pastanswers:
            randomanswer = [random.randint(0, 1) == 1] * n
            self.pastanswers[ID] = randomanswer
            return randomanswer
        return (self.pastanswers[ID] * n)[:n]

    def ask(self, n, ID):
        if self.firstexam:
            self.firstexam = False
            self.exam = [random.randint(0, 1) == 1] * n
        return (self.exam * n)[:n]

```
> 2 votes

# Answer
One bot of my own:

# Thomas

A traveler from a far-away land, has some dangerous ideas about past results being indicative of future performance. He uses those to keep other bots down, unless that stifles his own advancement.

<pre><code>class Thomas:
    def __init__(self,ID,n):
        N=10
        self.ID=ID
        self.myrank=n
        self.lowerank=0
        #The highest number of questions is equal to the number of participants, so we can do this:
        self.probs=[{i:1.0/N for i in np.linspace(0,1,num=N)} for i in np.arange(n)]
        self.output=[0.5]*n

    def ask(self,n,ID):
        if self.myrank==1 and self.lowerrank > 1: #I can't advance without promoting somebody first
            return [self.output[i]>np.random.rand() for i in np.arange(n)]
        #Otherwise, try to step on their fingers by going against the expected probability
        return [self.output[i]<np.random.rand() for i in np.arange(n)]

    def answer(self,n,ID):
        return [self.output[i]>np.random.rand() for i in np.arange(n)]

    def update(self,rankList,ownExam,otherExams):
        #Update our ranks
        self.myrank=len([i for i in rankList if i==rankList[self.ID]])
        self.lowerrank=len([i for i in rankList if i==rankList[self.ID]-1])
        #Update our expectations for each input we've been given
        self.bayesianupdate(ownExam[0])
        for ex in otherExams:
            self.bayesianupdate(ex[1])
        #Compress into output variable
        self.output=[np.sum([l[entry]*entry for entry in l]) for l in self.probs]

    def bayesianupdate(self,data):
        for i in np.arange(len(data)):
            if data[i]: #Got a True
                self.probs[i].update({entry:self.probs[i][entry]*entry for entry in self.probs[i]})
            else: #Got a False
                self.probs[i].update({entry:self.probs[i][entry]*(1-entry) for entry in self.probs[i]})
            s=np.sum([self.probs[i][entry] for entry in self.probs[i]]) #Renormalize
            self.probs[i].update({entry:self.probs[i][entry]/s for entry in self.probs[i]})
```
</code></pre>
> 2 votes

# Answer
# Beta

*Read the chat before downvoting. These bots don't violate any rules. The OP is even encouraging cooperating bots.*

Beta is forming a team together with Alpha. Both are using a predefined set of exams to help each other rise up the ranks. Also both are taking advantage of bots using the same exams over and over.

```
import numpy as np
import hashlib

class Beta:
    def __init__(self,ID,n):
        self.alpha = hashlib.md5(b"Alpha")
        self.beta = hashlib.md5(b"Beta")
        self.asker = -1
        self.alphas = set(range(n)).difference([ID])
        self.fixed = set(range(n)).difference([ID])
        self.fixedExams = [[]] * n

    def ask(self,n,ID):
        if ID in self.alphas:
            return self.md5ToExam(self.beta, n)
        else:
            return list(np.random.choice([True, False], n))

    def answer(self,n,ID):
        self.asker = ID
        if self.asker == -1:
            return [True] * n
        elif self.asker in self.fixed and len(self.fixedExams[self.asker]) > 0:
            return (self.fixedExams[self.asker] * n)[:n]
        elif self.asker in self.alphas:
            return self.md5ToExam(self.alpha, n)
        else:
            return list(np.random.choice([True, False], n))

    def update(self,rankList,ownExam,otherExams):
        if self.asker >= 0:
            if self.asker in self.alphas and ownExam[0] != self.md5ToExam(self.alpha, len(ownExam[0])):
                    self.alphas.remove(self.asker)
            if self.asker in self.fixed:
                l = min(len(ownExam[0]), len(self.fixedExams[self.asker]))
                if ownExam[0][:l] != self.fixedExams[self.asker][:l]:
                    self.fixed.remove(self.asker)
                    self.fixedExams[self.asker] = []
                elif len(ownExam[0]) > len(self.fixedExams[self.asker]):
                    self.fixedExams[self.asker] = ownExam[0]
        self.alpha.update(b"Alpha")
        self.beta.update(b"Beta")

    def md5ToExam(self, md5, n):
        return [x == "0" for x in bin(int(md5.hexdigest(), 16))[2:].zfill(128)][:n]

```
> 2 votes

# Answer
# Gamma

*Read the chat before downvoting. These bots don't violate any rules. The OP is even encouraging cooperating bots.*

Gamma has discovered the plans of Alpha and Beta and is trying to take advantage of both of them by disguising as one of them.

```
import numpy as np
import hashlib

class Gamma:
    def __init__(self, ID, n):
        self.alpha = hashlib.md5(b"Alpha")
        self.beta = hashlib.md5(b"Beta")
        self.asker = -1
        self.alphas = set(range(n)).difference([ID])
        self.betas = set(range(n)).difference([ID])
        self.fixed = set(range(n)).difference([ID])
        self.fixedExams = [[]] * n

    def ask(self,n,ID):
        if ID in self.alphas:
            return self.md5ToExam(self.beta, n)
        elif ID in self.betas:
            return self.md5ToExam(self.alpha, n)
        else:
            return self.md5ToWrongExam(np.random.choice([self.alpha, self.beta], 1)[0], n)

    def answer(self,n,ID):
        self.asker = ID
        if self.asker == -1:
            return [True] * n
        elif self.asker in self.fixed and len(self.fixedExams[self.asker]) > 0:
            return (self.fixedExams[self.asker] * n)[:n]
        elif self.asker in self.alphas:
            return self.md5ToExam(self.alpha, n)
        elif self.asker in self.betas:
            return self.md5ToExam(self.beta, n)
        else:
            return list(np.random.choice([True, False], n))

    def update(self,rankList,ownExam,otherExams):
        if self.asker >= 0:
            if self.asker in self.alphas and ownExam[0] != self.md5ToExam(self.alpha, len(ownExam[0])):
                    self.alphas.remove(self.asker)
            if self.asker in self.betas and ownExam[0] != self.md5ToExam(self.beta, len(ownExam[0])):
                    self.betas.remove(self.asker)
            if self.asker in self.fixed:
                l = min(len(ownExam[0]), len(self.fixedExams[self.asker]))
                if ownExam[0][:l] != self.fixedExams[self.asker][:l]:
                    self.fixed.remove(self.asker)
                    self.fixedExams[self.asker] = []
                elif len(ownExam[0]) > len(self.fixedExams[self.asker]):
                    self.fixedExams[self.asker] = ownExam[0]
        self.alpha.update(b"Alpha")
        self.beta.update(b"Beta")

    def md5ToExam(self, md5, n):
        return [x == "0" for x in bin(int(md5.hexdigest(), 16))[2:].zfill(128)][:n]

    def md5ToWrongExam(self, md5, n):
        return [x == "1" for x in bin(int(md5.hexdigest(), 16))[2:].zfill(128)][:n]

```
> 2 votes

# Answer
# Equalizer

Everyone should be equal (with none of this silly emperor nonsense), so provide as much social mobility as possible. Make the questions really easy (the answer is always True) so that people can succeed.

```
class Equalizer:
    def __init__(self, ID, n):
        self.previousAnswers = [[0, 0] for _ in range(n)]
        self.previousAsker = -1

    def ask(self, n, ID):
        return [True] * n

    def answer(self, n, ID):
        if ID == -1:
            return [True] * n

        # Assume that questions from the same bot will usually have the same answer.
        t, f = self.previousAnswers[ID]
        return [t >= f] * n

    def update(self, rankList, ownExam, otherExams):
        if self.previousAsker == -1:
            return

        # Keep track of what answer each bot prefers.
        counts = self.previousAnswers[self.previousAsker]
        counts[0] += ownExam[0].count(True)
        counts[1] += ownExam[0].count(False)

```
> 1 votes

# Answer
# TitForTat

Asks you easy questions if you asked it easy questions in the past. If you have never given it an exam, it defaults to easy questions.

Additionally, does not trust anyone who asks difficult questions, and will give them unpredictable answers.

```
import numpy as np

class TitForTat:
    def __init__(self, ID, n):
        self.friendly = [True] * n
        self.asker = -1

    def make_answers(self, n, ID):
        if ID == -1 or self.friendly[ID]:
            return [False] * n
        else:
            return list(np.random.choice([True, False], n))

    def ask(self, n, ID):
        return self.make_answers(n, ID)

    def answer(self, n, ID):
        self.asker = ID
        return self.make_answers(n, ID)

    def update(self, rankList, ownExam, otherExams):
        if self.asker != -1:
            # You are friendly if and only if you gave me a simple exam
            self.friendly[self.asker] = all(ownExam[0])

```

This bot works well if other bots cooperate with it. Currently only Equaliser cooperates, but this should hopefully be enough.
> 1 votes

# Answer
# Contrary

The Jade Emperor is always right, so it implements the Jade Emperor's asking function as its own answer function when it needs more than 2 answers. For only 1 answer it answers `true` (decent odds of being correct) and for 2 it answers `true,false` (this response passes "at least half" of the questions three out of four possible quizzes, better than choosing at random).

Uses similar logic in its Update with regards to how it alters its asking pattern, but its asking logic is similar to the Jade Emperor's, just with a different weight. Fluctuates between higher values of `true` with higher values of `false` when too many candidates score high enough to pass.

```
class Contrary:
    def __init__(self,ID,n):
        self.rank = 0
        self.ID = ID
        self.competitors = {}
        self.weight = -2
        pass

    def ask(self,n,ID):
        if self.weight > 0:
            num=min(np.random.exponential(scale=np.sqrt(np.power(self.weight,n))),np.power(2,n)-1)
            bi=list(np.binary_repr(int(num),width=n))
            return [x=='0' for x in bi]
        else:
            num=min(np.random.exponential(scale=np.sqrt(np.power(-self.weight,n))),np.power(2,n)-1)
            bi=list(np.binary_repr(int(num),width=n))
            return [x=='1' for x in bi]

    def answer(self,n,ID):
        if n == 1:
            return [True]
        if n == 2:
            return [True,False]
        num=min(np.random.exponential(scale=np.sqrt(np.power(2,n))),np.power(2,n)-1)
        bi=list(np.binary_repr(int(num),width=n))
        return [x=='0' for x in bi]

    def update(self,rankList,ownExam,otherExams):
        self.rank = rankList[self.ID];
        if len(otherExams) == 0:
            return
        correctCounts = [0 for i in otherExams[0][0]]
        for ourExam, response in otherExams:
            for i in range(len(response)):
                if ourExam[i] == response[i]:
                    correctCounts[i] += 1

        meanWhoAnsweredCorrectly = sum(correctCounts) / len(correctCounts)
        for i in range(len(correctCounts)):
            if correctCounts[i]+1 > meanWhoAnsweredCorrectly:
                self.weight = np.copysign(np.random.uniform(1,3),-self.weight)

```
> 0 votes

# Answer
# Marx

This is the Marx bot. He believes that, instead of a bureaucracy, we should have a communist system. To help reach this goal, it gives harder quizzes to higher ranking bots. It also gives more random answers to quizzes from higher bots, because they are probably cleverer, because they are higher up.

```
import numpy as np

class Marx():
    def __init__(self, ID, n):
        self.ID = ID
        self.n = n
        self.ranks = [] # The bot rankings
        self.e = [] # Our quiz
        self.rank = 0 # Our rank
    def ask(self, n, ID):
        test = [True] * n
        # Get the rank of the bot being quizzed
        if self.ranks:
            rank = self.ranks[ID]
        else:
            rank = 0
        for i in range(len(test)):
            item = test[i]
            if np.random.uniform(0, rank / self.n) > 0.5:
                # If the bot is higher ranking, make the quiz harder
                item = np.random.choice([True, False], 1)[0]
            test[i] = item
        # IF the test is not long enough, add Falses to the end
        while len(test) < n - 1:
            test.append(False)
        return test
    def answer(self, n, ID):
        # Get the rank of the asking bot
        if self.ranks:
            rank = self.ranks[ID]
        else:
            rank = 0
        if self.e:
            # Pad our quiz with Falses so it will not throw IndexError
            while len(self.e) < n:
                self.e.append(False)
            for i in range(len(self.e)):
                item = self.e[i]
                if np.random.uniform(0, rank / self.n) > 0.5:
                    # Assume that higher ranking bots are cleverer, so add more random answers
                    item = np.random.choice([True, False], 1)[0]
                self.e[i] = item
            if len(self.e) > self.rank + 1:
                self.e = self.e[:self.rank + 1]
            return self.e
        else:
            # If it is the first round, return all Trues
            return [True] * n
    def update(self, rankList, ownExam, otherExams):
        # Update our list of ranks
        self.ranks = rankList
        # Store the quiz we were given, to give to the next bot
        self.e = ownExam[0]
        # Store our rank
        self.rank = rankList[self.ID]

```
> 0 votes

---
Tags: king-of-the-hill, python
---


title: Typing, but to the left

text:
# Question
Title: Typing, but to the left
# Background

You've been given a task to take notes for a meeting. You start typing on your Google Doc, but you don't have enough time during the meeting to look at your keyboard while you type.

Fortunately for you, you can type without looking at your keyboard. After the meeting, you realize that everything you typed was one key to the left.

# The Challenge

For this challenge, you will be using the letters, numbers, and space bar of the QWERTY keyboard layout.

* Given an input of text (from any standard input method), output the resulting text, where every character is moved one to the left on the keyboard.

+ For the majority of letters, just look at the letter and translate it to the letter to the left (`c` becomes `x`, `t` becomes `r`, etc).
    + For letter `q`, translate to a literal tab character (`\t`).
    + For letter `a`, enable caps lock, so the capitalization of the rest of the string is reversed.
    + For letter `z`, capitalize the next letter in the string.
    + No translation is required for the space bar.
* Preserve capitalization while translating, and be mindful of caps lock (if caps lock is enabled, make sure the case is the opposite).
* All characters in the input string will be letters, numbers, or a space. No punctuation or other characters can be included.

# Test Cases

<sup>`\t` *is a literal tab character*</sup>

```
Hello world    -> Gwkki qieks
Code Golf      -> Xisw Fikd
Queried apples -> \tyweuws OOKWA

```

# Scoring

Lowest score in bytes wins. Have fun!

# Answer
# JavaScript (V8), 271 bytes

```
f=(s,k='~!@#$%^&*()_+`1234567890-=\tQWERTYUIOP{}|\tqwertyuiop[]\\ASDFGHJKL:"\n\\asdfghjkl;\'ZXCVBNM<>?zxcvbnm,./')=>s.replace(/[^ ]/g,c=>k[k.indexOf(c)-1]).replace(/\\([^\\]*)\\?/g,(m,c)=>c.replace(/[a-zA-z]/g,l=>l>'Z'?l.toUpperCase():l.toLowerCase())).replace(/[?']/,"")

```

Try it online! My first JavaScript code golf. It could definitely be shorter, but I think this is a good start.
It basically finds each character in the `k` string and replaces it with the previous one, then swaps the case of everything between the `A` or `a`, and removes all occurences of `Z` or `z` (as shift key does nothing on its own).
This should be a normal QWERTY keyboard layout, but let me know if not.
> 11 votes

# Answer
# Python 3, 211 bytes

```
d=' ~!@#$%^&*()`~1!2@3#4$5%6^7&8*9(0)		qQwWeErRtTyYuUiIoOpPaAsSdDfFgGhHjJkKlLzZxXcCvVbBnNmM  '
c=s=0
for i in input():k=d.find(i);print(end=d[k-2+(c*i.isalpha()^s)*(1-k%2*2)][i in'aAzZ':]);c^=i in'aA';s=i in'zZ'

```

Try it online!

Uses a lookup string in which the normal character and its shift-modified version are grouped together. For each character in the input, it will retreive the character two places to the left. Changes capitalization by adding `1` (or `-1` if the current character is uppercase) to the lookup value when shift XOR caps lock is active. Numbers are not influenced by the caps lock modifier.
> 5 votes

# Answer
# C (gcc), 276 bytes

```
i;j;k;h;l;m;n;o;f(char*b){char*c=calloc(m=strlen(b),1),*a=" \tqwertyuiop\aasdfghjkl\nzxcvbnm\tQWERTYUIOP\aASDFGHJKL\nZXCVBNM`1234567890";for(i=k=j=n=0;j<=m;l=a[i=index(a,b[j++])-a-1])k=l^7?k:!k,o=l>64&l<91?a[i-30*k]:l<97?h=i?l^7?l?l^10?l:0:32:0:0:a[i+29*k],o?c[n++]=o:n;b=c;}

```

Thanks to ceilingcat for -33 bytes.

Try it online!
> 2 votes

# Answer
# Red, 218 bytes

```
func[t][c: z: 0 rejoin collect[foreach s t[case[find"Aa"s[c: c xor 32]find"Zz"s[z: 32]on
[keep(select/case"  poiuytrewq^-lkjhgfdsamnbvcxzPOIUYTREWQ^-LKJHGFDSAMNBVCXZ0987654321~"s)xor either s <#"Z"[0][c xor z]z: 0]]]]]

```

Try it online!

Currently `AaZz` don't affect digits.
> 2 votes

# Answer
# PHP, 227 bytes

```
for(;''<$s=$argn[$i++];)$s!=a&&$s!=A?$s!=z&&$s!=Z?($t=$m[stripos($m='~1!2@3#4$5%6^7&8*9(0	qwertyuiopasdfghjklzxcvbnm',$s)-1])+(print$s>' '?$s<A?!$h?$s-1?$s?$s-1:9:'`':$t:($t>=A&&(($s<a)+$h+$c)%2?$t^' ':$t):$s)+$h=0:$h=1:$c=!$c;

```

Try it online!

I have created a mapping string (`~1!2@3#4$5%6^7&8*9(0 qwertyuiopasdfghjklzxcvbnm`) which for each digit has their SHIFT mode on the left and for each letter has the letter/key to their left.

I loop over input characters and for each character:

* If character is `a` or `A`, caps lock flag gets reversed (logical not).
* If character is `z` or `Z`, shift flag is set to `1`.
* When character is not in `aAzZ`:
    + Character to the left of current character in the mapping string is stored in `$t`.
    + If current character is an space, it is printed.
    + If current character is a digit, and if shift flag is `1`, `$t` is printed, else, if digit is `1`, ``` is printed, if digit is `0`, `9` is printed and otherwise, `digit-1` is printed.
    + If current character is a letter, based on status of shift flag, caps lock flag and casing of current character (lower/upper), `$t` in lower or upper case is printed. The only special case here is tab character, which is printed as is.
    + Shift flag is always set back to `0` at the end.
> 2 votes

---
Tags: code-golf, string, keyboard
---


title: Tips for golfing in MathGolf

text:
# Question
Title: Tips for golfing in MathGolf
What general tips do you have for golfing in MathGolf? I'm looking for ideas that can be applied to code golf problems in general that are at least somewhat specific to MathGolf (for tips which can be applied to loads of programming languages, look at the general tips).

# Answer
Writing `513` in a MathGolf program will push three separated digits (`5`;`1`;`3`), instead of the number `513` itself.
In MathGolf there are therefore quite a lot of 1-byte builtins for numbers: `-3` through and including `38`; `60`; `64`; `100`; `128`; `256`; `512`; `1000`; `1024`; `2048`; `3600`; `4096`; `10000`; `86400`; `100000`; `1000000`; `10000000`; `100000000`.

However, for other numbers it can sometimes be tricky to find the shortest way to generate it, so here an overview of the integers in the range `[1, 1000]`:

*NOTE: This is W.I.P. I will add more when I have some time. I was unable to make an evaluation program to check all possibilities (thus far), so these were done by hand.. I've also made it a community wiki, so if anyone else finds shorter alternatives or wants to continue with the numbers, feel free to edit it.*
Of course many variations can be found for certain numbers, as can be seen here and here. So the list below contains just one of the shortest variations.

```
-3-0:   d, c, b, 0
1-10:   1, 2, 3, 4, 5, 6, 7, 8, 9, ♂
11-20:  A, B, C, D, E, ☻, F, G, H, I
22-30:  J, K, L, M, N, O, P, Q, R, S
31-40:  T, ♥, U, V, W, X, Y, Z, Z), Z⌠
41-50:  Dx, J∞, Vx, K∞, K∞), L∞, L∞), M∞, 7², N∞       TODO: 2-byters for 45,47
51-60:  Ex, O∞, Wx, P∞, ♂f, Q∞, ╟╫, R∞, ╟(, ╟
61-70:  ☻x, T∞, Xx, ♦, ♦), U∞, U∞), V∞, V∞), W∞        TODO: 2-byters for 67,69
71-80:  Fx, X∞, Yx, Y∞, Y∞), Z∞, Z∞), Z∞⌠, ♦E+, ♦F+    TODO: 2-byters for 75,77,78,79,80
81-90:  Gx, Qx, Zx, Zx), Zx⌠, ♦K+, ♦L+, R■, ♂f, ♦O+    TODO: 2-byters for 84,85,86,87,90
91-100: Hx, Rx, ♦R+, T■, ♦T+, ♦♥+, ♦U+, ♀⌡, ♀(, ♀      TODO: 2-byters for 93,95,96,97
TODO: Continue through 1000

```

Here is a universal constant-generating method in MathGolf. Example (generating 513):

```
û☺☻$

```

This defines a two-character string and takes its ord code. The ord code of  is 2, and the ord code of  is 1. The ord code of this string is therefore `2*256+1=513`.

Taking the ord code also works for single characters. (Constants generated by this method are likely to be unoptimal.) This one returns 2.

```
'☻$

```

Also works for string length 3 and so on...

```
ùUTS$
83*256*256+84*256+85=5461077

```
> 4 votes

# Answer
This post tries to explain how the compressed strings work in MathGolf (a canonical feature for golfing languages).

This mechanism is actually quite simple: say you are trying to decompress the character `Σ` via the  instruction.

First of all, this character is 0xE4 in CP437. We then pass this through a lookup table. (We are decompressing using , which has the lookup table `etaoinsrdluczbfp`. There is one other such table `gwymvkxjqh ?*#.,`.)

We realize that the E'th character (in hex) in the lookup table is f. The 4th character in the lookup table is `i`. So we get the decompressed string `fi`.

> The way I do it is that I check the reference page and Code page 437, and I match the column and the row of the character within the code page with the indices of the string I want. So, ╕ means indexing in the string etaoinsrdluczbfp. In that string, b has index 13, z has index 12, and t has index 1. Thus, I look at row 13 and column 12 for bz, which is character ▄. Then I look at row 12 and column 1 for zt, which is character ┴. --maxb

---

For the sake of completeness I will also explain the dictionary:  pushes top 256 dictionary words. The word is indexed by the next character in the program, and the index is 0-indexed.  uses a number on the stack.
> 1 votes

---
Tags: code-golf, tips
---


title: Explore a Klarner-Rado sequence

text:
# Question
Title: Explore a Klarner-Rado sequence
One of the Klarner-Rado sequences is defined as follows:

* the first term is \\$1\\$
* for all subsequent terms, the following rule applies: if \\$x\\$ is present, so are \\$2x+1\\$ and \\$3x+1\\$
* the sequence is strictly increasing

This is A002977.

The first few terms are:

```
1, 3, 4, 7, 9, 10, 13, 15, 19, 21, 22, 27, ...

```

(\\$3\\$ is present because it's \\$2\times1+1\\$, \\$4\\$ is present because it's \\$3\times1+1\\$, \\$7\\$ is present because it's \\$2\times3+1\\$, etc.)

### Your task

Given \\$n\\$, you must return the \\$n\\$th element of the sequence. You may use either 0-based or 1-based indexing. (Please specify your choice in your answer.)

*0-indexed example:*

```
input = 10
output = 22

```

Let's see who can get less bytes...

*Also featured on codewars*

# Answer
> 3 votes
# 05AB1E, ~~15~~ 14 bytes

```
$FDx>DŠ+)˜ê}sè

```

Try it online!

# Answer
> 2 votes
# JavaScript (ES6),  ~~53~~  50 bytes

1-indexed.

```
n=>(g=k=>n?g(g[k]|!k++?g[n--,k*2]=g[k*3]=k:k):k)``

```

Try it online!

### Commented

**Note**: On the first iteration, we have `k = ['']`, which is zero-ish but truthy. By doing `!k++`, we force `k` to be coerced to \\$0\\$ *right away* (and not just before it's incremented), which makes the test work as expected.

```
n => (                    // n = requested index
  g = k =>                // h is a recursive function taking k, starting at 0
    n ?                   // if n is not equal to 0:
      g(                  //   do a recursive call:
        g[k] |            //     if g[k] is defined
        !k++ ?            //     or k = 0 (increment k after the test):
          g[n--, k * 2] = //       decrement n; set g[k * 2]
          g[k * 3] = k    //       and g[k * 3] and pass k
        :                 //     else:
          k               //       just pass k
      )                   //   end of recursive call
    :                     // else:
      k                   //   stop recursion and return k
)``                       // initial call to g with k = [''] (zero-ish)

```

---

# JavaScript (ES6), 65 bytes

I thought the `'11'[k/x-2]` trick was neat, but overall this initial approach is far too long.

0-indexed.

```
n=>(g=k=>a[n]||g(-~k,a.some(x=>'11'[k/x-2])&&a.push(k+1)))(a=[1])

```

Try it online!

### Commented

```
n => (                  // n = requested index
  g = k =>              // g is a recursive function taking k (starting at 1)
    a[n] ||             // if a[n] is defined, return it and stop
    g(                  // otherwise, do a recursive call:
      -~k,              //   with k + 1
      a.some(x =>       //   if there exists some x in a[]
        '11'[k / x - 2] //   such that k / x is either 2 or 3 ...
      )                 //
      && a.push(k + 1)  //   ... then push k + 1 in a[]
    )                   // end of recursive call
)(a = [1])              // initial call to g with k = a = [1]

```

# Answer
> 1 votes
# , 57 bytes

```
n=scan();for(i in 1:n)T=sort(unique(c(T,T%o%2:3+1)));T[n]

```

Try it online!

1-based index.

# Answer
> 1 votes
# APL+WIN, 54 bytes

Index origin 1

Prompts for the index of required value. Given the response that I received from Grimy and Shaggy that I can assume infinite memory and time then it is trivial to modify this function to work with a series up to the limit of your machine by increasing the value 20 in the function below. This version is limited to index position 1901981

```
m←1⋄(⍎∊20⍴⊂'m←(0≠1,-2-/m)/m←m[⍋m←m,∊1+m×¨⊂2 3]⋄')⋄m[⎕]

```

For some reason this function will not run on Dyalog Classic in TIO which is what I usually use.

On my machine 1 =\> 1, 11 =\> 22 and 61 =\> 237 (checked on http://oeis.org)

# Answer
> 0 votes
# JavaScript (ES6), 99 bytes

```
x=>eval("a=[i=1],a.b=a.includes;while(i++,c=i-1,x)a.b(i)||!a.b(c/2)&&!a.b(c/3)||(a.push(i),x--);c")

```

# Answer
> 0 votes
# Python 3, 73 bytes

```
f=lambda n,i=0,k=[1]:(i==n)*k[i]or f(n,i+1,sorted(k+[2*k[i]+1,3*k[i]+1]))

```

Try it online!

---
Tags: code-golf, sequence, array, linear-algebra
---