title: Convert AWG to Inches

text:
# Question
Title: Convert AWG to Inches
AWG (American Wire Gauge) is a common way of specifying wire sizes. Your task in this challenge is to convert from a given gauge to the diameter of the wire in inches.

The size in inches for the gauges from `4/0` to `40` are shown in the table below:

## Gauge to inches table

```
| AWG | Diameter (Inches) |
|-----|-------------------|
| 4/0 | 0.46              |
| 3/0 | 0.4096            |
| 2/0 | 0.3648            |
| 1/0 | 0.3249            |
| 1   | 0.2893            |
| 2   | 0.2576            |
| 3   | 0.2294            |
| 4   | 0.2043            |
| 5   | 0.1819            |
| 6   | 0.162             |
| 7   | 0.1443            |
| 8   | 0.1285            |
| 9   | 0.1144            |
| 10  | 0.1019            |
| 11  | 0.0907            |
| 12  | 0.0808            |
| 13  | 0.072             |
| 14  | 0.0641            |
| 15  | 0.0571            |
| 16  | 0.0508            |
| 17  | 0.0453            |
| 18  | 0.0403            |
| 19  | 0.0359            |
| 20  | 0.032             |
| 21  | 0.0285            |
| 22  | 0.0253            |
| 23  | 0.0226            |
| 24  | 0.0201            |
| 25  | 0.0179            |
| 26  | 0.0159            |
| 27  | 0.0142            |
| 28  | 0.0126            |
| 29  | 0.0113            |
| 30  | 0.01              |
| 31  | 0.00893           |
| 32  | 0.00795           |
| 33  | 0.00708           |
| 34  | 0.0063            |
| 35  | 0.00561           |
| 36  | 0.005             |
| 37  | 0.00445           |
| 38  | 0.00397           |
| 39  | 0.00353           |
| 40  | 0.00314           |

```

## Clarifications

* For gauges less than `0`, you can take the input as either `3/0` or `000`
* You only have to support from the given `4/0` to `40`
* The Wikipedia page has some helpful formulas you can try to use if you don't want to hardcode everything
* Output your answers to at least 3 sig-figs
* This , so shortest code in **bytes** wins!

# Answer
# , ~~33~~ 26 bytes

```
0.46%92^39%~*@".{3+".,~1-#

```

Try it online!

Takes input as a string with gauges less than zero as a string of zeroes. Finds the index of that string and divides 0.46 (the diameter of `0000`) by the 39th root of 92 (the ratio between gauges) that many times.

## Explanation

```
0.46%92^39%~*@".{3+".,~1-#  Input: string S
                         #  Length of S
                       1-   Subtract it from 1
                   ".,~     Eval S and append it, forms [1-len(S), eval(S)]
                 3+         Add 3 to each
            *@".            Sign of the eval
                {           Use that to index into the previous list
        39%~                Divide by 39
     92^                    Raise 92 to that power
0.46%                       Divide 0.46 by that and return

```
> 3 votes

# Answer
## JavaScript (ES7), 36 bytes

```
s=>.46/92**(((+s||1-s.length)+3)/39)

```

Takes input in "0000" format.
> 3 votes

# Answer
# Bash + GNU utils, 47

```
bc -l<<<"e(l(92)*(36-(${1/\/0/*-1+1}))/39)/200"

```

Straightforward arithmetic expression evaluation using `bc`. Input given as a command-line parameter.

Gauges less than 0 are given as `n/0`. The bash parameter expansion `${1/\/0/*-1+1}` converts these to -ve numbers and adds one which makes the arithmetic come out right.

`bc -l` gives 20 decimal places by default. `bc`'s exponentiation operator `^` can only handle integer exponents so `ln(y*e(x))` is used instead.

Try it online.
> 1 votes

# Answer
# Jelly, 18 bytes

```
VoLC$+3÷39µ92*.46÷

```

**Try it online!**

A monadic link taking a tring and returning a number. The `'0...0'` cases produce some extra output, but the return value is correct, as may be seen by ignoring the first two lines here.

### How?

```
VoLC$+3÷39µ92*.46÷ - Main link: guageString
V                  - evaluate as Jelly code (a string of zeros evaluates to 0)
    $              - last two links as a monad
  L                -     length
   C               -     complement (1-length)
 o                 - Or (integer value for > 0, 1-lenght for strings of zeros)
     +3            - add 3
       ÷39         - divide by 39
          µ        - monadic chain separation (call the result p)
              .46÷ - 0.46 divided by
           92*     - 92 raised to the power of p

```
> 1 votes

# Answer
# Python 3, 45 bytes

```
lambda s:.46/92**((3+(int(s)or 1-len(s)))/39)

```

**Try it online!**
> 0 votes

# Answer
# 05AB1E, ~~25~~ 23 bytes

```
8Ø50/92ID1‹ig(>}3+39/m/

```

Try it online!

**Explanation**

```
8Ø                       # push the 8th prime (0-indexed) = 23
  50/                    # divide by 50 = 0.46
     92                  # push 92
       I                 # push input
        D1‹i   }         # if input < 1
            g(>          # calculate -len(input)+1
                3+       # add 3
                  39/    # divide by 39
                     m   # raise 92 to this power
                      /  # divide 0.46 by this

```
> 0 votes

# Answer
# Excel, ~~53~~ 49 bytes

```
=92^((36-IF(ISNUMBER(A1),A1,49-CODE(A1)))/39)/200

```

Takes gauges less than Zero as String (1/0, 2/0 etc.)
> 0 votes

# Answer
# Perl 5, 39 + 1 (-p) = 40 bytes

```
s/(.).0/1-$1/e;$_=.005*92**((36-$_)/39)

```

Try it online!

Takes the bigger gauges as "n/0".
> 0 votes

---
Tags: code-golf, conversion, electrical-engineering
---


title: Generate The SUDSI Sequence

text:
# Question
Title: Generate The SUDSI Sequence
The SUDSI sequence (**su**m, **d**ifference, **s**wap, **i**ncrement) is a curious integer sequence that appears to exhibit rather chaotic behavior. It can be generated as follows:

Let *S* be an infinite list of the natural numbers: `1 2 3 4 5 6 ...`. Let *Si* denote the one-indexed *i*th element of *S*. So initially, *S1* is 1, *S2* is 2, etc. (there is no *S0*).

Starting with *S1* and *S2* ...

* Compute their sum: `*sum* = *S<sub>1</sub>* + *S<sub>2</sub>*`
* Compute their absolute difference (the larger one minus the smaller one): `*diff* = |*S<sub>1</sub>* - *S<sub>2</sub>*|`
* Swap the two values in *S* at the indices of the sum and difference: `swap(*S<sub>sum</sub>*, *S<sub>diff</sub>*)`
* Increment the indices of *S* you are working with. So next time you will compute the sum and difference of *S2* and *S3*, and the time after that it will be *S3* and *S4*, etc.
* Repeat this process indefinitely.

Here are the first few stages of *S* as this process is applied. The brackets `[]` surround the two values that are about to be summed and differenced.

Original *S*:

```
[1 2] 3 4 5 6 7 8 9 10 11 12 ...

```

After *S3* (`3 = 1 + 2`) and *S1* (`1 = |1 - 2|`) are swapped:

```
3 [2 1] 4 5 6 7 8 9 10 11 12 ...

```

After *S3* and *S1* are swapped:

```
1 2 [3 4] 5 6 7 8 9 10 11 12 ...

```

After *S7* and *S1* are swapped:

```
7 2 3 [4 5] 6 1 8 9 10 11 12 ...

```

After *S9* and *S1* are swapped:

```
9 2 3 4 [5 6] 1 8 7 10 11 12 ...

```

After *S11* and *S1* are swapped:

```
11 2 3 4 5 [6 1] 8 7 10 9 12 ...

```

After *S7* and *S5* are swapped:

```
11 2 3 4 1 6 [5 8] 7 10 9 12 ...

```

etc.

**The SUDSI sequence is defined as the sequence of the first elements in each of these lists.** So the first few terms of the SUDSI sequence are `1 3 1 7 9 11 11`.

Here are the first 200 terms of the SUDSI sequence (20 per line):

```
1 3 1 7 9 11 11 11 15 15 19 19 19 19 19 19 19 19 19 19
19 19 19 19 19 19 19 19 57 59 59 59 59 59 59 59 59 59 77 79
81 83 85 87 89 91 91 91 91 91 91 91 91 91 91 91 91 91 115 115
121 123 125 127 127 127 127 127 137 139 141 143 145 147 147 147 147 147 147 147
147 147 147 147 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167
167 167 167 167 209 211 211 211 211 211 221 223 223 223 223 223 223 223 223 223
223 223 243 243 243 243 243 243 257 259 261 263 263 263 263 263 263 263 263 263
263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263
263 263 325 327 329 331 331 331 331 331 331 331 331 331 349 351 351 351 351 351
361 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363

```

It is unclear (to me at least) how one might predict future terms. It only feels safe to say that that the terms are always odd, non-decreasing (after the second term), and that some numbers are repeated lots of times.

# Challenge

Write a program or function that takes in a positive integer *n* and prints or returns the *n*th term of the SUDSI sequence. For example, if *n* is 1, the output is `1`, if *n* is 2, the output is `3`, if *n* is 200, the output is `363`.

Take input in any usual way (stdin/command line/function arg).
**The shortest answer in bytes wins.**
(That site encodes things in UTF-8, but you may use any darn existing encoding you want.)

Mathy bonus: (potentially eligible for bounty)

* Tell me more about the SUDSI sequence. What's the underlying pattern to what numbers are part of it and how many of them there are (and stuff like that)? (I couldn't find SUDSI on OEIS by the way.)

# Answer
# Pyth, ~~45~~ ~~41~~ ~~40~~ 38 bytes

```
MXGH_HhugGm@Gtd,s<>GH2.a-@GH@GhHtQr1yQ

```

I noticed (as did Martin Büttner), that the maximum affected number of a permutation step at `k` is `2k + 1`. But since we only have `n - 1`, steps, we only need a list of the numbers up to `2n - 1`.

Try it online: Demonstration

```
M                       define a function g(G, H): return
                        (G is the list of numbers, H is a tuple)
 XGH_H                     a translation of G
                           (replaces the elements in H with the elements in reversed H)
                           in this application it swaps two values in the list G

                        implicit: Q = input()
 u     tQr1yQ           reduce, G = [1, 2, ..., 2*Q-1]
                        for each H in [0, 1, ..., Q - 2]:
                           G =
  gG...                        g(G, ...)
h                       print the first element of the resulting list

And the second argument ... of the function call g is:

     ,                  create the tuple (
      s<>GH2               sum(G[H:][:2]),
            .a-@GH@GhH     abs(G[H],G[H+1])
                        )
m@Gtd                   and map each value d to G[d - 1]

```
> 5 votes

# Answer
# Mathematica, 88 bytes

```
Last[f@n_:=n;(r=f@1;{f@a,f@b}={f[b=+##],f[a=Abs[#-#2]]};r)&@@f/@{#,#+1}&/@Range@Input[]]

```

This is a full program, reading the input from a prompt. It's a very direct implementation of the definition, where I'm keeping track of the current sequence in `f` (whose values `f[n]` default to `n`).

Here is a slightly more readable version:

```
Last[
  f@n_ := n;
  (
    r = f@1;
    {f@a,f@b} = {f[b=+##],f[a=Abs[#-#2]]};
    r
  ) & @@ f /@ {#,#+1} & /@ Range @ Input[]
]

```

## Some analysis

I've plotted the first 2000 elements of the sequence (it doesn't really get more interesting afterwards):

So the sequence is essentially linear with slope 2 and always has a few of those steps. It seems that the steps grow sublinearly (if they aren't even bounded), since they become barely noticeable as you increase the number of points you plot.

We can justify the linear growth quite easily (this is a bit handwavy, but I think it would hold up to a rigorous proof by induction): initially, the maximum affected number of a permutation step at `n` is `n + (n+1) = 2n + 1`. Also note that these numbers will always be moved to `1`, since `|n - (n+1)| = 1`. So it's not surprising that we get numbers which are approximately `2n` in the sequence. However, we can also note that for steps up to *n*, *Sn+1* is always bounded by *n+1*, which means that no swapping step can swap two numbers which are both greater than *n*. Hence, numbers that still need to be processed will be less than or equal to their initial value. Hence, `2n + 1` is also the bound for the sequence itself.

I think finding an argument for the length of the steps will be trickier.
> 18 votes

# Answer
# CJam, ~~45 40~~ 39 bytes

Just a naive approach. ~~Can be golfed further.~~ Missing a array swap function too much.

```
ri_K*,\{\:L>2<L1$:+:S@:-z:DL=tDSL=t}/1=

```

How it works:

```
ri_                             "Read the input, convert to integer and copy it";
   K*,                          "Multiply the copy by 20 and get 0 to 20*input-1 array";
      \{ ... }/1=               "Swap and put input on stack and run the loop that many";
                                "times. After the loop, take the second element as";
                                "we have a 0 based array while series is 1 based";
{\:L>2<L1$:+:S@:-z:DL=tDSL=t}
 \:L                            "Swap to put iteration index behind the array";
                                "and store array in L";
    >2<                         "In each loop, the iteration index will be on stack";
                                "Get the two elements from the array starting at that";
       L1$                      "Put the array on stack and copy the tuple";
          :+:S                  "Get the sum and store it in S";
              @:-z:D            "Get the absolute difference of the tuple and store in D";
                    L=t         "Put the element at S diff at sum index";
                       DSL=t    "Put the element at S sum at diff index";

```

Try it online here
> 4 votes

# Answer
# Haskell, 95 bytes

```
f#n=let b=f$n+1;l=f n+b;r=abs$f n-b;y x|x==l=f r|x==r=f l|1<2=f x in y
p n=foldl(#)id[1..n-1]$1

```

Usage example: `p 70` -\> `139`

I do not store the sequence in a list or array. I repeatedly update the identity function to a function with the two elements of the current step swapped. After `n` steps I call the resulting function with parameter `1`.
> 4 votes

# Answer
# J, 63 bytes

```
3 :'{.>((1-~{(+,|@-)]{~1+[)|.@:{`[`]}])&.>/(<"*i.1-y),<>:i.3*y'

```

Usage and tests:

```
   f=.3 :'{.>((1-~{(+,|@-)]{~1+[)|.@:{`[`]}])&.>/(<"*i.1-y),<>:i.3*y'

   f 5
9
   f every 1+i.20
1 3 1 7 9 11 11 11 15 15 19 19 19 19 19 19 19 19 19 19

```

Try it online here.
> 2 votes

# Answer
# Python 2, ~~117~~ ~~106~~ 101

```
j=input();a=range(3*j)
for i in range(1,j):b,c=a[i:i+2];d=abs(b-c);a[b+c],a[d]=a[d],a[b+c]
print a[1]

```

~~Uses a `dict` (map) to save the values to use arbitrary indices. `g(n)` is a function returning the `n`th item. Then just iterates `input-1` times and outputs the first item.~~

It turns out it's shorter using the methods from my Pyth answer.

Thanks to xnor for saving 5 bytes.
> 1 votes

# Answer
# Pyth, ~~55~~ ~~53~~ 51

Can probably be golfed further. ~~Might get really slow for large `n` as I was lazy to figure out how long of an array I'd need and just used a `n^n` one.~~

Thanks to Volatility and Martin Büttner for pointing out that I can use a maximum of `3n`.

```
KU*3QFNr1QJ@KN=G@tKNAJG,+JG.a-JG=Y@KJ XXKJ@KGGY)@K1

```

## Explanation

```
                   Q = input (implicit)
KU*3Q              K = range(3 * Q)
FNr1Q              for N in range(1, Q):
 J@KN               J = K[N]
 =G@tKN             G = K[1:][N]
 AJG,+JG.a-JG       J, G = J + G, abs(J - G)
 =Y@KJ              Y = K[J]
 XXKJ@KGGY          K[J], K[G] = K[G], Y
)
@K1                print K[1]

```
> 1 votes

# Answer
# Go 150

```
func f(j int){a:=make([]int,j*2);for i:=range a{a[i]=i};for i:=1;i<j;i++{b,c:=a[i],a[i+1];v:=b-c;if v<0{v*=-1};a[b+c],a[v]=a[v],a[b+c]};println(a[1])}

```

Ungolfed, nothing tricky, mostly stolen from @Pietu1998

```
func f(j int) {
    a := make([]int, j*2) // Build the array we will be working on
    for i := range a {
        a[i] = i
    }
    for i := 1; i < j; i++ {
        b, c := a[i], a[i+1]
        v := b - c
        if v < 0 {
            v *= -1
        }
        a[b+c], a[v] = a[v], a[b+c]
    }
    println(a[1])
}

```

http://play.golang.org/p/IWkT0c4Ev5
> 1 votes

# Answer
# Java, 162

```
int f(int n){int a[]=new int[2*n],s,d,x,t;for(x=0;x<2*n;)a[x]=++x;for(x=0;++x<n;){s=a[x]+a[x-1]-1;d=Math.abs(a[x]-a[x-1])-1;t=a[s];a[s]=a[d];a[d]=t;}return a[0];}

```

## Explanation

```
int f(int n) {
    int a[] = new int[2 * n], sum, diff, x, temp;
    for (x = 0; x < 2 * n;) {
        a[x] = ++x;  // set initial array
    }
    for (x = 0; ++x < n;) {
        sum = a[x] + a[x - 1] - 1;
        diff = Math.abs(a[x] - a[x - 1]) - 1;
        temp = a[sum];
        a[sum] = a[diff];
        a[diff] = temp;
    }
    return a[0];
}

```
> 1 votes

# Answer
# dc, ~~134~~ ~~132~~ 131 bytes

```
[_1*]sOdsn2*ddslsSsa[ladd:S1-dsa0<P]dsPx1d0rsN:N[la1+dsad;SdS@r1+;SdS@rL@L@r+Ss-d0>Od;SrLsdSsrLs;Sr:S:S1;SladsN:Nlaln>G]dsGxln1-;Nf

```

Use `echo $n $code | dc`, where `$n` is *n* and `$code` is...the code (*gasp*). Quote to taste.

Edit: Unless you pester me for an explanation, I will never get around to it.
> 1 votes

# Answer
# Perl 5, 131

A naive solution (i.e. a direct implementation of the definition). A subroutine, it takes input as a list of `1`s of the desired length.

```
{map$a[$_]=$_,1..3*@_;($a[$a[$_-1]+$a[$_]],$a[abs($a[$_-1]-$a[$_])])=($a[abs($a[$_-1]-$a[$_])],$a[$a[$_-1]+$a[$_]])for 2..@_;$a[1]}

```

Visualize its output by e.g. `print sub...->(1,1,1,1,1)`.

Explanation:

`map$a[$_]=$_,1..3*@_` builds the array `@a`, indexing each integer by itself from 1 to 3 times the size of `@_` (the input).

`($a[$a[$_-1]+$a[$_]],$a[abs($a[$_-1]-$a[$_])])=($a[abs($a[$_-1]-$a[$_])],$a[$a[$_-1]+$a[$_]])for 2..@_` repeats the switcheroo repeatedly (one fewer times than the size of `@_`), switching `$a[$a[$_-1]+$a[$_]]` with `$a[abs($a[$_-1]-$a[$_])]` as `$_` ranges from 2 to the size of `@_`.

And then the subroutine returns `$a[1]`.
> 0 votes

# Answer
# Perl 5, 90 + 1 (-p) = 91 bytes

```
@a=0..3*$_;$_=(map{@a[$d,$s]=@a[$s=$a[$_]+$a[$_-1],$d=abs$a[$_]-$a[$_-1]];$a[1]}1..$_)[-1]

```

Try it online!
> 0 votes

---
Tags: code-golf, number, number-theory, sequence
---


title: Take me to your leaderboard

text:
# Question
Title: Take me to your leaderboard
Have you ever found a good challenge to answer, answered it and then found out somebody posted a solution with a better score in *the same language*?

## Challenge

Write a **program/function** that takes a **PPCG question ID** and outputs a **leaderboard**.

A leaderboard consists of the rank, the language, the score, the author and the URL of each answer. This can be output as a newline delimited string, a list of strings, a "dictionary", etc..

* **Rank**
    + The rank of an answer is its **position in the score hierarchy (lowest first)**.
    + Answers with shared scores **must have the same rank**.
* **Language**
    + The name of the language is always between the last `#` on the first line and the first `,`.
    + It may be a link to documentation, which must be handled by taking the user-facing text.
* **Score**
    + The score of a answer is the **last number on the first line**.
    + It may be a decimal number.
* **Author**
    + The author of an answer is the **display name of the user** that posted it.
* **URL**

### Specifications

* Standard I/O rules **apply**.
* Standard loopholes are **forbidden**.
* This challenge is not about finding the shortest approach in all languages, rather, it is about finding the **shortest approach in each language**.
* Your code will be **scored in bytes**, usually in the encoding UTF-8, unless specified otherwise.
* Explanations, even for "practical" languages, are **encouraged**.

## Test cases

Note that these show example output formats which need not be strictly followed. These examples were taken at the time of sandboxing, they might be outdated.

```
Input: 28821

1. PCRE flavor, score 40 by jimmy23013 (https://codegolf.stackexchange.com/a/31863)

Input: 92944

1. Jelly, score 12 by Dennis (https://codegolf.stackexchange.com/a/92958)
2. Befunge-98, score 38 by Hactar (https://codegolf.stackexchange.com/a/98334)
3. ><>, score 41 by Sp3000 (https://codegolf.stackexchange.com/a/92980)
4. TovTovTov, score 810147050 by Yaniv (https://codegolf.stackexchange.com/a/93048)

Input: 47604*

1. Pyth, score 28.08 by Jakube (https://codegolf.stackexchange.com/a/47642)
2. APL, score 39.6 by jimmy23013 (https://codegolf.stackexchange.com/a/47606)

Input: 133793

1. Lua, score 9.06 by TehPers (https://codegolf.stackexchange.com/a/135775)
2. C# (.NET Core), score 10.20 by Kamil Drakari (https://codegolf.stackexchange.com/a/135764)
3. Cubically, score 86.98 by Kamil Drakari (https://codegolf.stackexchange.com/a/137695)

```

\*Note that this challenge has 3 answers, however the GolfScript answer doesn't have a comma in the header which makes it undefined behaviour.

In a few better formats:

```
28821, 92944, 47604, 133793

28821 92944 47604 133793

28821
92944
47604
133793

```

This challenge was sandboxed.

# Answer
# C# (.NET Core), ~~1059~~ ~~1049~~ ~~1033~~ ~~998~~ 973 bytes

*Saved 53 bytes thanks to @TheLethalCoder.*
*Saved 25 bytes thanks to @Mr. Xcoder.*

```
using HtmlAgilityPack;namespace System.Linq{n=>{var u="http://codegolf.stackexchange.com/";var l=new Collections.Generic.List<Tuple<string,float,string,string>>();foreach(var x in new HtmlWeb().Load(u+"questions/"+n).GetElementbyId("answers").Descendants("div").Where(p=>(p.Attributes["id"]?.Value??"").Contains("answer-"))){var b=x.Descendants().First(p=>(p.Attributes["class"]?.Value)=="post-text");var h=b.Descendants().ElementAt(1).InnerText;l.Add(new Tuple<string,float,string,string>(h.Split(',',' ')[0],float.Parse(h.Split(' ').Reverse().First(p=>float.TryParse(p.Replace('.',','),out var y)).Replace('.', ',')),b.ParentNode.Descendants("td").Last(p=>(p.Attributes["class"]?.Value)=="post-signature").Descendants("div").Reverse().ElementAt(1).Descendants("a").First().InnerText,u+"a/"+x.Attributes["id"].Value.Split('-')[1]));}var s=new string[l.Count];for(var i=0;i<l.Count;){var m=l[i];s[i]=++i+$". {m.Item1}, score {m.Item2} by {m.Item3} ({m.Item4})";}return s;}}

```

Uses the HTMLAgilityPack.

There are probably better solutions to this using the StackOverflow API, but this is a raw HTML solution.

---

Ungolfed code: (Unchanged for readability & reference)

```
n =>
{
    // Retrieve the HTML of the question page with ID n
    var doc = new HtmlWeb().Load("https://codegolf.stackexchange.com/questions/" + n);
    // Get all the answers
    var answers = doc.GetElementbyId("answers").Descendants("div").Where(d => (d.Attributes["id"]?.Value ?? "").Contains("answer-"));

    // Format: Language, Score, Author, URL
    var l = new Collections.Generic.List<Tuple<string, float, string, string>>();

    // Loop over every answer element
    foreach (var a in answers)
    {
        // Get the content of the answer post
        var b = a.Descendants().First(d => (d.Attributes["class"]?.Value ?? "") == "post-text");
        // Get the header
        var h = b.Descendants().ElementAt(1);
        // Dummy variable for the TryParse
        float y;
        // Create a new Tuple
        var v = new Tuple<string, float, string, string>(
            h.InnerText.Split(',', ' ')[0], // The language
            float.Parse(h.InnerText.Split(' ').Reverse().First(x => float.TryParse(x.Replace('.',','), out y)).Replace('.', ',')), // The score of the answer
            b.ParentNode.Descendants("td").Last(d => (d.Attributes["class"]?.Value ?? "") == "post-signature").Descendants("div").Reverse().ElementAt(1).Descendants("a").First().InnerText, // The author
            "https://codegolf.stackexchange.com/a/" + a.Attributes["id"].Value.Split('-')[1] // The url to the answer
            );
        l.Add(v); // Add the tuple to the collection
    }
    var s = new string[l.Count]; // An array to save the leadboard content
    for (var i = 0; i < l.Count;i++)
    {
        var m = l[i]; // The current element
        s[i] = $"{i+1}. {m.Item1}, score {m.Item2} by {m.Item3} ({m.Item4})"; // Format the data
    }
    return s;
}

```
> 3 votes

# Answer
# Python 2 + requests + BeautifulSoup + re, 547 519 512 bytes

```
from requests import*
from bs4 import BeautifulSoup as B
import re
w,h='.stackexchange.com/','http://'
def D(i):l=B(i['body'].split('\n')[0],'html.parser').text;return[l.split(',')[0],float(re.findall(r'\d*\.\d+|\d+',l)[-1]),i['owner']['display_name'],'%scodegolf%sa/'%(h,w)+`i['answer_id']`]
d=sorted([D(i)for i in get('%sapi%squestions/%d/answers?site=codegolf&filter=withbody'%(h,w,input())).json()['items']],key=lambda x:x[1])
h=r=0
for x in d:r+=x[1]>h;h=x[1];print'%d. %s, score %f by %s (%s)'%tuple([r]+x)

```

Output for this question (137878):

```
1. Python 2 + requests + BeautifulSoup + re, score 512.000000 by Dopapp (http://codegolf.stackexchange.com/a/138043)
2. C# (.NET Core), score 973.000000 by Ian H. (http://codegolf.stackexchange.com/a/137933)

```

Ungolfed:

```
from requests import*
from bs4 import BeautifulSoup
import re

# [score, owner, lang, link]
def data(item): # extracts data from each answer
    owner = item['owner']['display_name']
    link = 'http://codegolf.stackexchange.com/a/'+`item['answer_id']`
    line1 = BeautifulSoup(item['body'].split('\n')[0], 'html.parser').text # first line of the answer
    lang = line1.split(',')[0]
    score = float(re.findall(r'\d*\.\d+|\d+', line1)[-1])
    return [score, owner, lang, link]

# datas :P
datas = [data(item)for item in get('http://api.stackexchange.com/questions/%d/answers?site=codegolf&filter=withbody'%input()).json()['items']]

sortedDatas = sorted(datas, key=lambda x: x[0]) # sort the data by the score

highestScore=rank=0 # This is for doing the ranking in case there are identical scores
for d in sortedDatas:
    if d[0] > highestScore:
        highestScore = d[0]
        rank += 1
    print '%d. %s, score %f by %s (%s)' % (rank, d[2], d[0], d[1], d[3]) # format the line

```
> 2 votes

---
Tags: code-golf, internet, stack-exchange-api
---


title: KOTH - Loaded RPS

text:
# Question
Title: KOTH - Loaded RPS
# Contest permanently opened - Updated August 10th 2017

Even though on June 5th 2017 I declared a winner (who will be kept as the best answer) I'll be rnning new bots and updating the results.

# June 5th Results

Congratulations user1502040

Since there are no ties, I only show the % of matches won.

`Statistician2` \- 95.7%
`Fitter` \- 89.1%
`Nash` \- 83.9%
`Weigher` \- 79.9%
`ExpectedBayes` \- 76.4%
`AntiRepeater` \- 72.1%
`Yggdrasil` \- 65.0%
`AntiGreedy` \- 64.1%
`Reactor` \- 59.9%
`NotHungry` \- 57.3%
`NashBot` \- 55.1%
`Blodsocer` \- 48.6%
`BestOfBothWorlds` \- 48.4%
`GoodWinning` \- 43.9%
`Rockstar` \- 40.5%
`ArtsyChild` \- 40.4%
`Assassin` \- 38.1%
`WeightedRandom` \- 37.7%
`Ensemble` \- 37.4%
`UseOpponents` \- 36.4%
`GreedyPsychologist` \- 36.3%
`TheMessenger` \- 33.9%
`Copycat` \- 31.4%
`Greedy` \- 28.3%
`SomewhatHungry` \- 27.6%
`AntiAntiGreedy` \- 21.0%
`Cycler` \- 20.3%
`Swap` \- 19.8%
`RandomBot` \- 16.2%

I created a Google Sheet with the grid of results of each pairing: https://docs.google.com/spreadsheets/d/1KrMvcvWMkK-h1Ee50w0gWLh\_L6rCFOgLhTN\_QlEXHyk/edit?usp=sharing

---

Thanks to the Petri Dilemma I found myself able to handle this King of the Hill.

# The game

The game is a simple "Rock-Paper-Scissors" with a twist: Points gained with each victory increase during the match (your R, P or S get loaded).

* Paper wins Rock
* Scissors wins Paper
* Rock wins Scissors

The winner gets as many points as his load on his play.

The loser increases by 1 the load on his play.

In the case of a tie, each player increases the load on his play by 0.5.

After 100 plays, the one with more points is the winner.

e.g.: P1 has loads \[10,11,12\] (Rock, Paper, Scissors) and P2 \[7,8,9\]. P1 plays R, P2 plays P. P2 wins and gets 8 points. P1 loads become \[11,11,12\], P2 loads stay the same.

# Challenge specifications

Your program must be written in Python (sorry, I don't know how to handle it otherwise). You are to create a function that take each of these variables as an argument on each execution:

```
my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history

```

`points` \- Current points (yours and your opp)

`loaded`\- Array with loads (in order RPS) (yours and your opp)

`history`\- String with all plays, last character is the last play (yours and your opp)

You must return `"R"`, `"P"` or `"S"`. If you would return something different, it would be an automatic lose of the match.

# Rules

You cannot change built-in functions.

# Testing

I'll keep a Git updated with the code and all the bots compiting: https://github.com/Masclins/LoadedRPS

# Judging

The winner will be decided by selecting the person with the most win matches after 1000 full round-robin. Ties will be broken by matches tied. 1000 matches are being played rather than one because I expect a lot of randomness, and that way the randomness would be less relevant.

You can submit up to 5 bots.

The contest ends on ~~July~~June 4th (that will be the last day I'll accept any answer), and on ~~July~~June 5th I'll post the final stadings (might try to post an advancemnt before).

---

Since this is my first KOTH, I'm 100% opened to changing anything for improvement, such as the number of matches played against each bot.

Edited to 1000 matches, since I see there really is quite randomness involved.

# Answer
## ~~Statistician~~ (no longer playing)

```
import random
import collections

R, P, S = moves = range(3)
move_idx = {"R": R, "P": P, "S": S}
name = "RPS"
beat = (P, S, R)
beaten = (S, R, P)

def react(_0, _1, _2, _3, _4, opp_history):
    if not opp_history:
        return random.randrange(0, 3)
    return beat[opp_history[-1]]

def anti_react(_0, _1, _2, _3, _4, opp_history):
    if not opp_history:
        return random.randrange(0, 3)
    return beaten[opp_history[-1]]

def random_max(scores):
    scores = [s + random.normalvariate(0, 1) for s in scores]
    return scores.index(max(scores))

def greedy_margin(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    scores = [my_loaded[move] - opp_loaded[beat[move]] for move in moves]
    return random_max(scores)

def anti_greedy(my_points, opp_pints, my_loaded, opp_loaded, my_history, opp_history):
    scores = [-my_loaded[move] for move in moves]
    return random_max(scores)

def recent_stats(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    opp_history = opp_history[-10:-1]
    counts = collections.Counter(opp_history)
    scores = [(counts[beaten[move]] + 1) * my_loaded[move] -
              (counts[beat[move]] + 1) * opp_loaded[move] for move in moves]
    return random_max(scores)

def statistician(_0, _1, _2, _3, my_history, opp_history):
    m1 = []
    o1 = []
    my_loaded = [0] * 3
    opp_loaded = [0] * 3
    my_points = 0
    opp_points = 0
    strategies = [react, anti_react, greedy_margin, anti_greedy, recent_stats]
    strategy_scores = [0 for _ in strategies]
    for i, (mx, ox) in enumerate(zip(my_history, opp_history)):
        mx = move_idx[mx]
        ox = move_idx[ox]
        for j, strategy in enumerate(strategies):
            strategy_scores[j] *= 0.98
            move = strategy(my_points, opp_points, my_loaded, opp_loaded, m1, o1)
            if move == beat[ox]:
                strategy_scores[j] += my_loaded[move]
            elif move == beaten[ox]:
                strategy_scores[j] -= opp_loaded[ox]
        m1.append(mx)
        o1.append(ox)
        if mx == beat[ox]:
            opp_loaded[ox] += 1
            my_points += my_loaded[mx]
        elif mx == beaten[ox]:
            my_loaded[mx] += 1
            opp_points += opp_loaded[ox]
        else:
            my_loaded[mx] += 0.5
            opp_loaded[ox] += 0.5
    strategy = strategies[random_max(strategy_scores)]
    return name[strategy(my_points, opp_points, my_loaded, opp_loaded, m1, o1)]

```

Switches between a few simple strategies based on expected past performance

## Statistician 2

```
import random
import collections
import numpy as np

R, P, S = moves = range(3)
move_idx = {"R": R, "P": P, "S": S}
names = "RPS"
beat = (P, S, R)
beaten = (S, R, P)

def react(my_loaded, opp_loaded, my_history, opp_history):
    if not opp_history:
        return random.randrange(0, 3)
    counts = [0, 0, 0]
    counts[beat[opp_history[-1]]] += 1
    return counts

def random_max(scores):
    scores = [s + random.normalvariate(0, 1) for s in scores]
    return scores.index(max(scores))

def argmax(scores):
    m = max(scores)
    return [s == m for s in scores]

def greedy_margin(my_loaded, opp_loaded, my_history, opp_history):
    scores = [my_loaded[move] - opp_loaded[beat[move]] for move in moves]
    return argmax(scores)

recent_counts = None

def best_move(counts, my_loaded, opp_loaded):
    scores = [(counts[beaten[move]] + 0.5) * my_loaded[move] -
              (counts[beat[move]] + 0.5) * opp_loaded[move] for move in moves]
    return argmax(scores)

def recent_stats(my_loaded, opp_loaded, my_history, opp_history):
    if len(opp_history) >= 10:
        recent_counts[opp_history[-10]] -= 1
    recent_counts[opp_history[-1]] += 1
    return best_move(recent_counts, my_loaded, opp_loaded)

order2_counts = None

def order2(my_loaded, opp_loaded, my_history, opp_history):
    if len(my_history) >= 2:
        base0 = 9 * my_history[-2] + 3 * opp_history[-2]
        order2_counts[base0 + opp_history[-1]] += 1
    base1 = 9 * my_history[-1] + 3 * opp_history[-1]
    counts = [order2_counts[base1 + move] for move in moves]
    return best_move(counts, my_loaded, opp_loaded)

def nash(my_loaded, opp_loaded, my_history, opp_history):
    third = 1.0 / 3
    p = np.full(3, third)
    q = np.full(3, third)
    u = np.array(my_loaded)
    v = np.array(opp_loaded)
    m0 = np.zeros(3)
    m1 = np.zeros(3)
    lr = 0.2
    for _ in range(10):
        de0 = u * np.roll(q, 1) - np.roll(v * q, 2)
        de1 = v * np.roll(p, 1) - np.roll(u * p, 2)
        m0 = 0.9 * m0 + 0.1 * de0
        m1 = 0.9 * m1 + 0.1 * de1
        p += lr * m0
        q += lr * m1
        p[p < 0] = 0
        q[q < 0] = 0
        tp, tq = np.sum(p), np.sum(q)
        if tp == 0 or tq == 0:
            return np.full(3, third)
        p /= tp
        q /= tq
        lr *= 0.9
    return p

strategies = [react, greedy_margin, recent_stats, order2, nash]

predictions = strategy_scores = mh = oh = None

def statistician2func(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    global strategy_scores, history, recent_counts, mh, oh, predictions, order2_counts
    if not opp_history:
        strategy_scores = [0 for _ in strategies]
        recent_counts = collections.Counter()
        order2_counts = collections.Counter()
        mh, oh = [], []
        predictions = None
        return random.choice(names)
    my_move = move_idx[my_history[-1]]
    opp_move = move_idx[opp_history[-1]]
    if predictions is not None:
        for j, p in enumerate(predictions):
            good = beat[opp_move]
            bad = beaten[opp_move]
            strategy_scores[j] += (my_loaded[good] * p[good] - opp_loaded[opp_move] * p[bad]) / sum(p)
    mh.append(my_move)
    oh.append(opp_move)
    predictions = [strategy(my_loaded, opp_loaded, mh, oh) for strategy in strategies]
    strategy = random_max(strategy_scores)
    p = predictions[strategy]
    r = random.random()
    for i, pi in enumerate(p):
        r -= pi
        if r <= 0:
            break
    return names[i]

```

## Nash

```
import numpy as np
import random

def nashfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    third = 1.0 / 3
    p = np.full(3, third)
    q = np.full(3, third)
    u = np.array(my_loaded)
    v = np.array(opp_loaded)
    m0 = np.zeros(3)
    m1 = np.zeros(3)
    lr = 0.2
    for _ in range(10):
        de0 = u * np.roll(q, 1) - np.roll(v * q, 2)
        de1 = v * np.roll(p, 1) - np.roll(u * p, 2)
        m0 = 0.9 * m0 + 0.1 * de0
        m1 = 0.9 * m1 + 0.1 * de1
        p += lr * m0
        q += lr * m1
        p[p < 0] = 0
        q[q < 0] = 0
        tp, tq = np.sum(p), np.sum(q)
        if tp == 0 or tq == 0:
            return random.choice("RPS")
        p /= tp
        q /= tq
        lr *= 0.9
    r = random.random()
    for i, pi in enumerate(p):
        r -= pi
        if r <= 0:
            break
    return "RPS"[i]

```

Computes an approximate Nash equilibrium by gradient descent.
> 8 votes

# Answer
# Weigher

I lost track of reasoning while experimenting with the code, but the basic idea is to estimate opponent's move probability by last 3 moves using some weights and multiply them by another weight which depends on loads. I thought that I can somehow use `my_loaded` too, but I couldn't decide how, so left it out.

```
def weigher(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    idx = {"R": 0, "P": 1, "S": 2}
    sc = [0, 0, 0]
    for i, m in enumerate(reversed(opp_history[-3:])):
        sc[idx[m]] += (1 / (1 + i))

    for i in range(3):
        sc[i] *= (opp_loaded[i] ** 2)

    return "PSR"[sc.index(max(sc))]

```

# Satan

Probably will be disqualified, because it's kind of cheating and it makes some assumptions about the testing function (it has to have opponent's function in a variable on its stack frame), but it doesn't technically break any current rules — it doesn't redefine or rewrite anything. It simply uses black magic to execute the opponent function to see what turn did/will they do. It cannot deal with randomness, but deterministic bots have no chance to defeat Satan.

```
def satan(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    import inspect, types
    f = inspect.currentframe()
    s = f.f_code.co_name
    try:
        for v in f.f_back.f_locals.values():
            if isinstance(v, types.FunctionType) and v.__name__ != s:
                try:
                    return "PSR"[{"R": 0, "P": 1, "S": 2}[
                        v(opp_points, my_points, opp_loaded, my_loaded, opp_history, my_history)]]
                except:
                    continue
    finally:
        del f

```
> 5 votes

# Answer
# Fitter

This Bot improves Pattern and fuses it with Economist (Pattern and Economist will no longer participate)

The improvement of Pattern is that the Bot now looks for two two kinds of patterns: Opponent reacting to his last play and opponent reacting to my last play. Then evaluates both predictions to use the one that fits the best.

From that pattern the Bot has now the probability for R, P and S. Taking that into account and the expected value of each play (as Economist did), the Bot plays the one that gives the most value.

```
import random
import numpy as np
def fitterfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
        t = len(opp_history)
        RPS = ["R","P","S"]
        if t <= 2:
                return RPS[t]
        elif t == 3:
                return random.choice(RPS)

        def n(c): return RPS.index(c)

        total_me = np.zeros(shape=(3,3))
        total_opp= np.zeros(shape=(3,3))
        p_me = np.array([[1/3]*3]*3)
        p_opp = np.array([[1/3]*3]*3)

        for i in range(1, t):
                total_me[n(my_history[i-1]), n(opp_history[i])] += 1
                total_opp[n(opp_history[i-1]), n(opp_history[i])] += 1
        for i in range(3):
                if np.sum(total_me[i,:]) != 0:
                        p_me[i,:] = total_me[i,:] / np.sum(total_me[i,:])
                if np.sum(total_opp[i,:]) != 0:
                        p_opp[i,:] = total_opp[i,:] / np.sum(total_opp[i,:])

        error_me = 0
        error_opp = 0

        for i in range(1, t):
                diff = 1 - p_me[n(my_history[i-1]), n(opp_history[i])]
                error_me += diff * diff
                diff = 1 - p_opp[n(opp_history[i-1]), n(opp_history[i])]
                error_opp += diff * diff

        if error_me < error_opp:
                p = p_me[n(my_history[-1]),:]
        else:
                p = p_opp[n(opp_history[-1]),:]

# From here, right now I weight values, though not 100% is the best idea, I leave the alternative in case I'd feel like changing it
        value = [(p[2]*my_loaded[0] - p[1]*opp_loaded[1], "R"), (p[0]*my_loaded[1] - p[2]*opp_loaded[2], "P"), (p[1]*my_loaded[2] - p[0]*opp_loaded[0], "S")]
        value.sort()

        if value[-1][0] > value[-2][0]:
                return value[-1][1]
        elif value[-1][0] > value[-3][0]:
                return random.choice([value[-1][1], value[-2][1]])
        else:
                return random.choice(RPS)

#       idx = p.tolist().index(max(p))
#       return ["P", "S", "R"][idx]

```

---

Here are the two old codes

# ~~Pattern~~ (no longer playing)

The Pattern tries to find patterns on his opponent. It looks what the opponent had played after the last play he did (giving more weight to the latter plays). Through that, it guesses what the opponent will play, and plays the countermatch to that.

```
import random
import numpy as np
def patternfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
        if len(opp_history) == 0:
                return random.choice(["R","P","S"])
        elif len(opp_history) == 1:
                if opp_history == "R":
                        return "P"
                elif opp_history == "P":
                        return "S"
                elif opp_history == "S":
                        return "R"

        p = np.array([1/3]*3)
        c = opp_history[-1]
        for i in range(1, len(opp_history)):
                c0 = opp_history[i-1]
                c1 = opp_history[i]
                if c0 == c:
                        p *= .9
                        if c1 == "R":
                                p[0] += .1
                        elif c1 == "P":
                                p[1] += .1
                        elif c1 == "S":
                                p[2] += .1

        idx = p.tolist().index(max(p))
        return ["P", "S", "R"][idx]

```

# ~~Economist~~ (no longer playing)

The Economist does the following: Guesses the probability of each play by the opponent by watching what he had played the last 9 turns. From that, computes the expected benefit of each play and goes with the one that has the best expected value.

```
import random
def economistfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
        if len(opp_history) == 0:
                return random.choice(["R","P","S"])
        if len(opp_history) > 9:
                opp_history = opp_history[-10:-1]
        p = [opp_history.count("R"), opp_history.count("P"), opp_history.count("S")]

        value = [(p[2]*my_loaded[0] - p[1]*opp_loaded[1], "R"), (p[0]*my_loaded[1] - p[2]*opp_loaded[2], "P"), (p[1]*my_loaded[2] - p[0]*opp_loaded[0], "S")]
        value.sort()

        if value[-1][0] > value[-2][0]:
                return value[-1][1]
        elif value[-1][0] > value[-3][0]:
                return random.choice([value[-1][1], value[-2][1]])
        else:
                return random.choice(["R","P","S"])

```
> 4 votes

# Answer
## Anti-Repeater

```
from random import choice
def Antirepeaterfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    s = opp_history.count("S")
    r = opp_history.count("R")
    p = opp_history.count("P")

    if s>p and s>r:
        return "R"
    elif p>s and p>r:
        return "S"
    else:
        return "P"

```

Picks paper on the first turn, after which it returns whatever beats what the opponent has done the most, picking paper in case of a tie.

## Copycat

```
import random
def copycatfunc(I,dont,care,about,these,enmoves):
    if not enmoves:
        return random.choice(["R","P","S"])
    else:
        return enmoves[len(enmoves)-1]

```

Simply copies the opponents last move.

## Anti-Anti-Greedy

```
from random import choice
def antiantigreedy(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    if opp_loaded[0] > opp_loaded[1] and opp_loaded[0] > opp_loaded[2]:
        return "S"
    if opp_loaded[1] > opp_loaded[0] and opp_loaded[1] > opp_loaded[2]:
        return "R"
    if opp_loaded[2] > opp_loaded[0] and opp_loaded[2] > opp_loaded[1]:
        return "P"
    else:
        return choice(["R","P","S"])

```

Picks whatever loses to the opponent's most heavily weighted choice.

## Somewhat Hungry

```
from random import choice
def somewhathungryfunc(blah, blah2, load, blah3, blah4, blah5):
    if load[0] > load[1] and load[0] < load[2] or load[0] < load[1] and load[0] > load[2]:
        return "R"
    if load[1] > load[0] and load[1] < load[2] or load[1] < load[0] and load[1] > load[2]:
        return "P"
    if load[2] > load[1] and load[2] < load[0] or load[2] < load[1] and load[2] > load[0]:
        return "S"
    else:
        return choice(["R","P","S"])

```
> 4 votes

# Answer
# Yggdrasil

This is named "Yggdrasil" because it looks ahead in the game tree. This bot does not perform any prediction of the opponent, it simply attempts to maintain a statistical advantage if it is given one (by balancing current and future profits). It calculates an approximately ideal mixed strategy, and returns a move selected randomly with those weights. If this bot were perfect (which it's not, because the state valuation function is pretty bad and it doesn't look very far ahead), then it would be impossible to beat this bot more than 50% of the time. I don't know how well this bot will do in practice.

```
def yggdrasil(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    cache = {}
    def get(turn, ml, ol):
        key = str(turn) + str(ml) + str(ol)
        if not key in cache:
            cache[key] = State(turn, ml, ol)
        return cache[key]

    def wrand(opts):
        total = sum(abs(w) for c,w in opts.items())
        while True:
            r = random.uniform(0, total)
            for c, w in opts.items():
                r -= abs(w)
                if r < 0:
                    return c
            print("error",total,r)

    class State():
        turn = 0
        ml = [1,1,1]
        ol = [1,1,1]
        val = 0
        strat = [1/3, 1/3, 1/3]
        depth = -1
        R = 0
        P = 1
        S = 2
        eps = 0.0001
        maxturn = 1000

        def __init__(self, turn, ml, ol):
            self.turn = turn
            self.ml = ml
            self.ol = ol
        def calcval(self, depth):
            if depth <= self.depth:
                return self.val
            if turn >= 1000:
                return 0
            a = 0
            b = -self.ol[P]
            c = self.ml[R]
            d = self.ml[P]
            e = 0
            f = -self.ol[S]
            g = -self.ol[R]
            h = self.ml[S]
            i = 0
            if depth > 0:
                a += get(self.turn+1,[self.ml[R]+1,self.ml[P],self.ml[S]],[self.ol[R]+1,self.ol[P],self.ol[S]]).calcval(depth-1)
                b += get(self.turn+1,[self.ml[R]+2,self.ml[P],self.ml[S]],[self.ol[R],self.ol[P],self.ol[S]]).calcval(depth-1)
                c += get(self.turn+1,[self.ml[R],self.ml[P],self.ml[S]],[self.ol[R],self.ol[P],self.ol[S]+2]).calcval(depth-1)
                d += get(self.turn+1,[self.ml[R],self.ml[P],self.ml[S]],[self.ol[R]+2,self.ol[P],self.ol[S]]).calcval(depth-1)
                e += get(self.turn+1,[self.ml[R],self.ml[P]+1,self.ml[S]],[self.ol[R],self.ol[P]+1,self.ol[S]]).calcval(depth-1)
                f += get(self.turn+1,[self.ml[R],self.ml[P]+2,self.ml[S]],[self.ol[R],self.ol[P],self.ol[S]]).calcval(depth-1)
                g += get(self.turn+1,[self.ml[R],self.ml[P],self.ml[S]+2],[self.ol[R],self.ol[P],self.ol[S]]).calcval(depth-1)
                h += get(self.turn+1,[self.ml[R],self.ml[P],self.ml[S]],[self.ol[R],self.ol[P]+2,self.ol[S]]).calcval(depth-1)
                i += get(self.turn+1,[self.ml[R],self.ml[P],self.ml[S]+1],[self.ol[R],self.ol[P],self.ol[S]+1]).calcval(depth-1)
            self.val = -9223372036854775808
            for pr in range(0,7):
                for pp in range(0,7-pr):
                    ps = 6-pr-pp
                    thisval = min([pr*a+pp*d+ps*g,pr*b+pp*e+ps*h,pr*c+pp*f+ps*i])
                    if thisval > self.val:
                        self.strat = [pr,pp,ps]
                        self.val = thisval
            self.val /= 6

            if depth == 0:
                self.val *= min(self.val, self.maxturn - self.turn)
            return self.val

    turn = len(my_history)
    teststate = get(turn, [x * 2 for x in my_loaded], [x * 2 for x in opp_loaded])
    teststate.calcval(1)
    return wrand({"R":teststate.strat[R],"P":teststate.strat[P],"S":teststate.strat[S]})

```
> 4 votes

# Answer
# The messenger

```
def themessengerfunc(I, do, not, need, these, arguments):return "P"

```

# Rockstar

```
def rockstarfunc(I, do, not, need, these, arguments):return "R"

```

# Assassin

```
def assassinfunc(I, do, not, need, these, arguments):return "S"

```

# Explanation

Now, you may think that these bots are entirely stupid.

not entirely true, these are actually based on idea, of amassing a huge bonus, and the enemy making a misstep and getting walloped with it.

now, these bots play very similarly to greedy, however, they are simpler, and do not randomly pick until they get a load on one weapon, they stick with their weapon of choice.

Another thing to note: these will each beat greedy around half the time, drawing a third of the time, and losing one sixth of the time. when they do win, they will tend to win by a lot. why is this?

Greedy, until he loses a round, will randomly pick a weapon. this means that when he does not win a round, he will pick a weapon randomly again, which could be a winning one again. if greedy draws or loses, he sticks with that weapon. if greedy wins at least one round, then picks the same weapon as the bot, greedy wins. if greedy picks the losing weapon at some point, our bot wins, because the load on our weapon would have been higher than the score greedy has.

Assuming greedy doesn't always just pick the winning weapon through grand chance, this will mean that the chances are:

1/3 : { 1/2 win (1/6 total). 1/2 lose (1/6 total). }

1/3 draw

1/3 win

so: 1/3 chance to draw, 1/6 chance of a loss, 1/2 chance to win.

this probably shows that you need to do multiple games of multiple rounds

these are mainly to get the challenge rolling
> 3 votes

# Answer
## Reactor

Makes the play that would have won the previous round.

```
import random
def reactfunc(I, dont, need, all, these, opp_history):
    if not opp_history:
        return random.choice(["R","P","S"])
    else:
        prev=opp_history[len(opp_history)-1]
        if prev == "R":
            return "P"
        if prev == "P":
            return "S"
        else:
            return "R"

```
> 3 votes

# Answer
# Artsy Child

This bot acts like a child playing arts and crafts, will start with paper and use either paper or scissors randomly, but will not use scissors after rock or scissors because she needs to use the scissors on paper. Will throw a rock back at anyone who throws a rock at her.

```
import random
def artsychildfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    if len(opp_history) == 0:
            return "P"
    elif opp_history[-1] == "R":
            return "R"
    elif my_history[-1] != "P":
            return "P"
    else:
            return random.choice(["P", "S"])

```
> 3 votes

# Answer
Here the three Bots I have build for testing:

---

# RandomBot

```
import random
def randombotfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
        return random.choice(["R","P","S"])

```

---

# Greedy

Simply chooses his most loaded option.

```
import random
def greedyfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
        if my_loaded[0] > my_loaded[1]:
                if my_loaded[0] > my_loaded[2]:
                        return "R"
                elif my_loaded[0] < my_loaded[2]:
                        return "S"
                else:
                        return random.choice(["R","S"])
        elif my_loaded[0] < my_loaded[1]:
                if my_loaded[1] > my_loaded[2]:
                        return "P"
                elif my_loaded[1] < my_loaded[2]:
                        return "S"
                else:
                        return random.choice(["P","S"])
        else:
                if my_loaded[0] > my_loaded[2]:
                        return random.choice(["R","P"])
                elif my_loaded[0] < my_loaded[2]:
                        return "S"
                else:
                        return random.choice(["R","P","S"])

```

---

# Antigreedy

Assumes opponent will play greedy and plays the winning alternative.

```
import random
def antigreedyfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
        if opp_loaded[0] > opp_loaded[1]:
                if opp_loaded[0] > opp_loaded[2]:
                        return "P"
                elif opp_loaded[0] < opp_loaded[2]:
                        return "R"
                else:
                        return "R"
        elif opp_loaded[0] < opp_loaded[1]:
                if opp_loaded[1] > opp_loaded[2]:
                        return "S"
                elif opp_loaded[1] < opp_loaded[2]:
                        return "R"
                else:
                        return "S"
        else:
                if opp_loaded[0] > opp_loaded[2]:
                        return "P"
                elif opp_loaded[0] < opp_loaded[2]:
                        return "R"
                else:
                        return random.choice(["R","P","S"])

```
> 2 votes

# Answer
### Not Hungry

```
def nothungryfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    if my_loaded[0] < my_loaded[1]:
            if my_loaded[0] < my_loaded[2]:
                    return "R"
            elif my_loaded[0] > my_loaded[2]:
                    return "S"
            else:
                    return random.choice(["R","S"])
    elif my_loaded[0] > my_loaded[1]:
            if my_loaded[1] < my_loaded[2]:
                    return "P"
            elif my_loaded[1] > my_loaded[2]:
                    return "S"
            else:
                    return random.choice(["P","S"])
    else:
            if my_loaded[0] < my_loaded[2]:
                    return random.choice(["R","P"])
            elif my_loaded[0] > my_loaded[2]:
                    return "S"
            else:
                    return random.choice(["R","P","S"])

```

This is literally the inverse of Greedy, it chooses the lowest points option available.
> 1 votes

# Answer
# Use Opponent's Favorite

```
from collections import Counter
import random
def useopponents(hi, my, name, is, stephen, opp_history):
  if opp_history:
    data = Counter(opp_history)
    return data.most_common(1)[0][0]
  else:
    return random.choice(["R","P","S"])

```

For the first turn, chooses a random item. For every other turn, uses the opponent's most common choice. If there is a tie, it defaults to the earliest most common choice.

//I stole code from here

---

# Winning is Good

```
import random
def goodwinning(no, yes, maybe, so, my_history, opp_history):
  if opp_history:
    me = my_history[len(my_history)-1]
    you = opp_history[len(opp_history)-1]
    if you == me:
      return goodwinning(no, yes, maybe, so, my_history[:-1], opp_history[:-1])
    else:
      if me == "R":
        if you == "P":
          return "P"
        else:
          return "R"
      elif me == "P":
        if you == "S":
          return "S"
        else:
          return "R"
      else:
        if you == "R":
          return "R"
        else:
          return "P"
  else:
    return random.choice(["R","P","S"])

```

Returns the choice of the winner of the previous round. If the previous round was a tie, recursively checks the round before that. If it was only ties, or it is the first round, returns a random choice.
> 1 votes

# Answer
# Best of Both Worlds

This bot basically combines Anti-Greedy and Greedy (hence the name).

```
def bobwfunc(a, b, my_loaded, opp_loaded, c, d):
    opp_max = max(opp_loaded)
    opp_play = "PSR"[opp_loaded.index(opp_max)]

    my_max = max(my_loaded)
    my_play = "RPS"[my_loaded.index(my_max)]

    if opp_play == my_play:
        return opp_play
    else:
        return my_play if opp_max < my_max else opp_play

```
> 1 votes

# Answer
# NashBot

```
import random
def nashbotfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    r = opp_loaded[0] * opp_loaded[2]
    p = opp_loaded[0] * opp_loaded[1]
    s = opp_loaded[1] * opp_loaded[2]
    q = random.uniform(0, r + p + s) - r
    return "R" if q < 0 else "P" if q < p else "S"

```

Randomly chooses between the three options in such a way that the opponent statistically has no preference between moves with regards to how much it scores; in other words, both Greedy and Not Hungry should have the same average expected score against it.
> 1 votes

# Answer
# Expectedbayes

## Edit: Updated Ranking

This is the new top ranking after inclusion of Expectedbayes:

* statistician2func 91.89%
* fitterfunc 85.65%
* nashfunc 80.40%
* weigherfunc 76.39%
* expectedbayesfunc 73.33%
* antirepeaterfunc 68.52%
* ...

## Explanations

(NB: post 05/06/2017 submission)

This bot tries to maximize the expected value of its next move by:

* Computing the probability for each of the opponent's next possible move
* Using that figure and the loads to compute the expected value for each of R,P and S
* Selecting the move that has the highest expected value
* Randomly selecting a value if predicting failed

Probabilities are updated every ten moves. The number of past moves used to compute the probabilities has been set to 10 for each bot (so 20 features overall). This is probably overfitting the data, but I did not try to check further.

It relies on the scikit library to compute the opponent's move probabilities (i am saying it in case I misread the rules and it was in fact not allowed).

It easily wins against bots that always make the same choice. Surprisingly, it is quite effective against the random bot with a 93% win rate (I believe this is due to the fact that it limits the number of points his opponent can get while maximizing its own number of possible points for each round).

I made a quick try with 100 turn and only a limited number of bots, and this is what I got from result\_standing:

* randombotfunc,35
* nashbotfunc,333
* greedyfunc,172
* antigreedyfunc,491
* themessengerfunc,298
* rockstarfunc,200
* statistician2func,748
* fitterfunc,656
* expectedbayesfunc,601

Which is not that bad!

```
from sklearn.naive_bayes import MultinomialNB
import random

#Number of past moves used to compute the probability of next move
#I did not really try to make such thing as a cross-validation, so this number is purely random
n_data = 10

#Some useful data structures
choices = ['R','P','S']
choices_dic = {'R':0,'P':1,'S':2}
point_dic = {(0,0):0,(1,1):0,(2,2):0, #Same choices
             (0,1):-1,(0,2):1, #me = rock
             (1,0):1,(1,2):-1, #me = paper
             (2,0):-1,(2,1):1} #me = scissor

def compute_points(my_choice,opp_choice,my_load,opp_load):
    """
    Compute points
    @param my_choice My move as an integer
    @param opp_choice Opponent choice as an integer
    @param my_load my_load array
    @param opp_load opp_load array
    @return A signed integer (+ = points earned, - = points losed)
    """
    points = point_dic[(my_choice,opp_choice)] #Get -1, 0 or 1
    if points > 0:
        return points*my_load[my_choice]
    else:
        return points*opp_load[opp_choice]

#This use to be a decision tree, before I changed it to something else. Nevertheless, I kept the name
class Decision_tree:
    def __init__(self):
        self.dataX = []
        self.dataY = []
        self.clf = MultinomialNB()

    def decide(self,my_load,opp_load,my_history,opp_history):
        """
        Returns the decision as an integer

        Done through a try (if a prediction could be made) except (if not possible)
        """
        try:
            #Let's try to predict the next move
            my_h = list(map(lambda x: choices_dic[x],my_history[-n_data:-1]))
            opp_h = list(map(lambda x: choices_dic[x],opp_history[-n_data:-1]))
            pred = self.clf.predict_proba([my_h+opp_h])
            #We create a points array where keys are the available choices
            pts = []
            for i in range(3):
                #We compute the expected gain/loss for each choice
                tmp = 0
                for j in range(3):
                    tmp += compute_points(i,j,my_load,opp_load)*pred[0][j]
                pts.append(tmp)
            return pts.index(max(pts)) #We return key for the highest expected value
        except:
            return random.choice(range(3))

    def append_data(self,my_history,opp_history):
        if my_history == "":
            self.clf = MultinomialNB()
        elif len(my_history) < n_data:
            pass
        else:
            my_h = list(map(lambda x: choices_dic[x],my_history[-n_data:-1]))
            opp_h = list(map(lambda x: choices_dic[x],opp_history[-n_data:-1]))
            self.dataX = self.dataX + [my_h+opp_h]
            self.dataY = self.dataY + [choices_dic[opp_history[-1:]]]

            if len(self.dataX) >= 10:
                self.clf.partial_fit(self.dataX,self.dataY,classes=[0,1,2])

                self.dataX = []
                self.dataY = []

#Once again, this is not actually a decision tree
dt = Decision_tree()

#There we go:
def expectedbayesfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    dt.append_data(my_history,opp_history)
    choice = choices[dt.decide(my_loaded,opp_loaded,my_history,opp_history)]
    return choice

```
> 1 votes

# Answer
# Cycler

```
def cycler(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    return "RPS"[len(myhistory)%3]

```

0
> 0 votes

# Answer
# b l o d s o c e r

***s o c e r y***

I gave it a fix, so it should probably work now I hope

I messed something up again so I deleted and undeleted. I am making a lot of mess ups.

```
def blodsocerfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    import random
    # tuned up an ready to go hopeful
    # s o c e r y
    if len(my_history) > 40 and len(set(opp_history[-30:])) == 1:
        if opp_history[-1] == "S":
            return "R"
        elif opp_history[-1] == "R":
            return "P"
        else:
            return "S"
        # against confused bots that only do one thing most of the time.
    elif len(my_history)>30 and min(opp_history.count(i) for i in "RPS")/max(opp_history.count(i) for i in "RPS") >0.8:
        return "RPS"[my_loaded.index(max(my_loaded))] # This is so if the other bot is acting errratic
                                                      # the max bonus is used for advantage
    elif len(my_history) < 10:
        if len(my_history) > 2 and all(i == "S" for i in opp_history[1:]):
            if len(my_history) > 5: return "S"
            return "P"
        return "S" # Be careful, because scissors are SHARP
    elif len(set(opp_history[1:10])) == 1 and len(my_history) < 20:
        if opp_history[1] == "S":
            return "R"
        elif opp_history[1] == "R":
            return "R"
        else:
            return "P"
    elif len(opp_history) -  max(opp_history.count(i) for i in "RPS") < 4 and len(my_history) < 30:
        if opp_history.count("R") > max(opp_history.count(i) for i in "PS"):
            return "P"
        if opp_history.count("P") > max(opp_history.count(i) for i in "RS"):
            return "S"
        if opp_history.count("S") > max(opp_history.count(i) for i in "RP"):
            return "R"
    elif len(my_history) < 15:
        if max(opp_loaded)<max(my_loaded):
            return "RPS"[len(my_history)%3]
        else:
            return "RPS"[(my_loaded.index(max(my_loaded))+len(my_history)%2)%3]
    elif len(my_history) == 15:
        if max(opp_loaded)<max(my_loaded):
            return "RPS"[(len(my_history)+1)%3]
        else:
            return "RPS"[(my_loaded.index(max(my_loaded))+ (len(my_history)%2)^1)%3]
    else:
        if max(opp_loaded)<max(my_loaded):
            return random.choice("RPS")
        else:
            return "RPS"[(my_loaded.index(max(my_loaded))+ (random.randint(0,1)))%3]

```
> 0 votes

# Answer
## Ensemble

```
from random import *
def f(I):
    if I==0:return "R"
    if I==1:return "P"
    return "S"
def b(I):
    if I=="R":return 0
    if I=="P":return 1
    return 2
def Ensemble(mp,op,ml,ol,mh,oh):
    A=[0]*3
    B=[0]*3
    if(len(oh)):
        k=b(oh[-1])
        A[k-2]+=0.84
        A[k]+=0.29
        for x in range(len(oh)):
            g=b(oh[x])
            B[g-2]+=0.82
            B[g]+=0.22
        s=sum(B)
        for x in range(len(B)):
            A[x]+=(B[x]*1.04/s)
        r=max(A)
    else:
        r=randint(0,3)
    return f(r)

```

Several competing algorithms vote on the best solution.

## Swap

```
from random import *
def f(I):
    if I==0:return "R"
    if I==1:return "P"
    return "S"
def b(I):
    if I=="R":return 0
    if I=="P":return 1
    return 2
def Swap(mp,op,ml,ol,mh,oh):
    A=[0]*3
    B=[0]*3
    if(len(mh)):
        r=(b(mh[-1])+randint(1,2))%3
    else:
        r=randint(0,3)
    return f(r)

```

Does a random move, but without repeating the last move it did.
> 0 votes

# Answer
# Weighted Random

Like RandomBot, but it picks only 2 to throw each time it is invoked. Will sometimes beat Rockstar or Assassin, but will pump up the scores of the other one (e.g., if it beats Rockstar, it gives Assassin a point boost).

```
import random

selection_set = ["R", "P", "S"]
selection_set.pop(random.randint(0,2))
def weightedrandombotfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    return random.choice(selection_set)

```
> 0 votes

# Answer
# Greedy psychologist

Named that because it defaults to greedy, but if it can't decide, it counters whatever the opponent would do if they used the greedy strategy. If it still can't decide, it goes randomly.

```
from random import choice

def greedypsychologistfunc(my_points, opp_points, my_loaded, opp_loaded, my_history, opp_history):
    greedy = get_my_move(my_loaded)
    combined = list(set(greedy) & set(get_opp_counter(opp_loaded)))

    if len(combined) == 0:
        return choice(greedy)
    return choice(combined)

def get_indexes(lst, value):
    return [i for i,x in enumerate(lst) if x == value]

def get_my_move(my_loaded):
    return ["RPS"[i] for i in get_indexes(my_loaded, max(my_loaded))]

def get_opp_counter(opp_loaded):
    return ["PSR"[i] for i in get_indexes(opp_loaded, max(opp_loaded))]

```
> 0 votes

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


title: Print a booklet

text:
# Question
Title: Print a booklet
Reading a book is easy, but printing a book can be a bit tricky. When printing a booklet, the printer needs to have the pages arranged in a certain manner in order to be read from left to right. The way this is done is using a pattern like below

```
n, 1, 2, n-1, n-2, 3, 4, n-3, n-4, 5, 6, n-5, n-6, 7, 8, n-7, n-8, 9, 10, n-9, n-10, 11, 12, n-11…

```

## Test Cases

4 page booklet: `4, 1, 2, 3`

8 page booklet: `8,1,2,7,6,3,4,5`

12 page booklet: `12,1,2,11,10,3,4,9,8,5,6,7`

16 page booklet: `16,1,2,15,14,3,4,13,12,5,6,11,10,7,8,9`

20 page booklet: `20,1,2,19,18,3,4,17,16,5,6,15,14,7,8,13,12,9,10,11`

## Task

Your task is to, given an integer `n` that is a multiple of 4, display an array of numbers that could be used to print a book of `n` pages.

**Note:** As long as the output generates the correct numbers, whether delimited by spaces, commas, hyphens, or parenthesis, any method to getting to a solution can be used

This is a question so answers will be scored in bytes, with the fewest bytes winning.

# Answer
> 8 votes
# 05AB1E, ~~9~~ ~~8~~ 7 bytes

```
L`[Žˆrˆ

```

Try it online!

**Explanation**

```
L           # push range [1 ... input]
 `          # split as separate to stack
  [Ž        # loop until stack is empty
    ˆ       # add top of stack to global list
     r      # reverse stack
      ˆ     # add top of stack to global list
            # implicitly display global list

```

# Answer
> 13 votes
## JavaScript (ES6), ~~49~~ 45 bytes

*Saved 4 bytes with help from @RickHitchcock*

```
f=(n,k=1)=>n<k?[]:[n,k,k+1,n-1,...f(n-2,k+2)]

```

### Demo

```
f=(n,k=1)=>n<k?[]:[n,k,k+1,n-1,...f(n-2,k+2)]

console.log(JSON.stringify(f(4)))
console.log(JSON.stringify(f(8)))
console.log(JSON.stringify(f(12)))
console.log(JSON.stringify(f(16)))
console.log(JSON.stringify(f(20)))
```

---

## Non-recursive, 51 bytes

```
n=>[...Array(n)].map((_,i)=>[2*n-i,,++i][i&2]+1>>1)

```

### Demo

```
let f =

n=>[...Array(n)].map((_,i)=>[2*n-i,,++i][i&2]+1>>1)

console.log(JSON.stringify(f(4)))
console.log(JSON.stringify(f(8)))
console.log(JSON.stringify(f(12)))
console.log(JSON.stringify(f(16)))
console.log(JSON.stringify(f(20)))
```

# Answer
> 6 votes
# Python 2, ~~99~~ ~~93~~ ~~88~~ ~~58~~ ~~56~~ 55 bytes

```
f=input()
for i in range(1,f/2,2):print-~f-i,i,i+1,f-i,

```

Try it online!

-6 bytes by removing unneeded indentation, thanks Oliver Ni

-5 bytes by changing the conditional, thanks Luis Mendo

-30 bytes by optimizing the print statements, thanks Arnold Palmer

-2 bytes by putting the loop on one line, thanks nedla2004

-1 byte by doing some wizardry, thanks Mr. Xcoder

# Answer
> 6 votes
# Python 3, ~~68~~ ~~63~~ 62 bytes

*−5 bytes thanks to @notjagan (removing spaces and using `[*...]` instead of `list()`).*

*−1 byte thanks to @ovs (`*1` instead of `[:]`)*.

```
def f(n):r=[*range(1,n+1)];return[r.pop(k%4//2-1)for k in r*1]

```

**Try it online!**

# Answer
> 6 votes
# Python 2, 46 bytes

```
lambda n:map(range(1,n+1).pop,n/4*[-1,0,0,-1])

```

Try it online!

Generates the range `[1..n]` and pops from the front and back in the repeating pattern `back, front, front, back, ...`

---

**Python 2, 49 bytes**

```
f=lambda n,k=1:n/k*[0]and[n,k,k+1,n-1]+f(n-2,k+2)

```

Try it online!

Generates the first 4 elements, then recursively continues with the upper value `n` decreased by 2 and the lower value `k` increased by 2.

---

**Python 2, 49 bytes**

```
lambda n:[[n-i/2,i/2+1][-i%4/2]for i in range(n)]

```

Try it online!

Directly generates the `i`'th value of the list, using `-i%4/2` as a Boolean for whether to take the lower or higher value.

# Answer
> 5 votes
# MATL, ~~19~~ ~~17~~ 10 bytes

```
:t"0&)@o?P

```

Try it online!

### Explanation

```
:          % Implicitly input n. Push range [1 2 ... n]
t          % Duplicate
"          % For each (that is, do n times)
  0&)      %   Push last element, and then subarray with remaining elements
  @        %   Push 1-based iteration index
  o?       %   Is it odd? If so
    P      %     Reverse subarray of remaining elements
           %   Implicit end
           % Implicit end
           % Implicitly display stack

```

# Answer
> 5 votes
# Jelly,  ~~12~~  11 bytes

Improved to 11 bytes, "Combinatorial Methods":

```
9Bṁ×ḶṚÆ¡‘Œ?

```

**Try it online!**

### How?

This uses permutation calculations and the factorial number system:

```
9Bṁ×ḶṚÆ¡‘Œ? - Link n                        e.g. 16
9B          - nine in binary                     [1,0,0,1]
  ṁ         - mould like n                       [1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1]
    Ḷ       - lowered range(n)                   [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
   ×        - multiply                           [0,0,0,3,4,0,0,7,8,0,0,11,12,0,0,15]
     Ṛ      - reverse                            [15,0,0,12,11,0,0,8,7,0,0,4,3,0,0,0]
      Æ¡    - convert from factorial base        19621302981954 (=15*15!+12*12!+...+3*3!)
        ‘   - increment                          19621302981955 (we actually wanted 1*0! too)
         Œ? - shortest permutation of natural numbers [1,2,...] that would reside at that
            -   index in a sorted list of all permutations of those same numbers
            -                                    [16,1,2,15,14,3,4,13,12,5,6,11,10,7,8,9]

```

---

Unimproved 12 byter, "Knitting Patterns":

```
RṚ‘żRs2Z€FḊṁ

```

**Try it online!**

### How?

This is the simple approach, it creates two strands, interleaves them and then trims the loose ends:

```
RṚ‘żRs2Z€FḊṁ - Link: n                      e.g. 8
R            - range(n)                          [1,2,3,4,5,6,7,8]
 Ṛ           - reverse                           [8,7,6,5,4,3,2,1]
  ‘          - increment                         [9,8,7,6,5,4,3,2]
    R        - range(n)                          [1,2,3,4,5,6,7,8]
   ż         - zip (interleave)                  [[9,1],[8,2],[7,3],[6,4],[5,5],[4,6],[3,7],[2,8]]
     s2      - split into chunks of length 2     [[[9,1],[8,2]],[[7,3],[6,4]],[[5,5],[4,6]],[[3,7],[2,8]]]
       Z€    - transpose €ach (cross-stitch?!)   [[[9,8],[1,2]],[[7,6],[3,4]],[[5,4],[5,6]],[[3,2],[7,8]]]
         F   - flatten                           [9,8,1,2,7,6,3,4,5,4,5,6,3,2,7,8]
          Ḋ  - dequeue (removes excess start)    [8,1,2,7,6,3,4,5,4,5,6,3,2,7,8]
           ṁ - mould like n (removes excess end) [8,1,2,7,6,3,4,5]

```

# Answer
> 4 votes
# Octave, ~~43~~ 36 bytes

A port of this answer in C (gcc) can be found here.

```
@(n)[n-(k=1:2:n/2)+1;k;k+1;n-k](:)';

```

# Explanation

1. `k=1:2:n/2`: Generates a linear sequence from 1 to `n/2` in steps of 2. Note that this is immediately used in the next step.
2. `[n-k+1;k;k+1;n-k]`: Creates a 4 row matrix such that the first row creates the sequence `n, n-2, n-4...` down to `n-(n/2)+2`, the second row is `1, 3, 5...` up to `n/2 - 1`, the third row is the second row added by 1 and the fourth row is the first row added by 1.
3. `[n-k+1;k;k+1;n-k](:)'`: This stacks all of the columns of this matrix together from left to right to make a single column vector, and we transpose it to a row vector for easy display. Stacking the columns together this way precisely creates the sequence desired.

Note that this is an anonymous function, so you can assign it to a variable prior to using it, or you can use the built-in `ans` variable that gets created after creating the function.

Try it online!

# Answer
> 3 votes
# , 48 bytes (improved)

Thanks to @Giuseppe for -7 bytes!

```
n=scan();(x=order(1:n%%2))[order(-(n/2+.5-x)^2)]

```

The trick is that `x=1:n;x[order(x%%2)]` is equivalent to `order(1:n%%2)`.

Try it online!

# , 55 bytes (original)

## Golfed

```
n=scan();x=1:n;x=x[order(x%%2)];x[order(-(n/2+.5-x)^2)]

```

## Ungolfed with comments

Read `n` from stdin.

```
n=scan()

```

Define `x` as sequence of pages from 1 to `n`.

```
x=1:n

```

Order pages so even pages are before uneven pages.

```
x=x[order(x%%2)]

```

Order pages in descending order with respect to the centre of the book computed by `n/2+.5`.

```
x[order(-(n/2+.5-x)^2)]

```

Example with 8 pages:

* centre is 4.5;
* pages 1 and 8 are the most distant from the centre, but 8 comes first because 8 is even;
* pages 2 and 7 are the next most distant from the centre, but 2 comes first as 2 is even;
* and so on.

Try it online!

# Answer
> 2 votes
# Mathematica, ~~54~~ ~~53~~ 45 bytes

```
Join@@Range[#][[(-1)^k{k,-k}]]~Table~{k,#/2}&

```

## Explanation

```
Join@@Range[#][[(-1)^k{k,-k}]]~Table~{k,#/2}&  (* Input: # *)
                              ~Table~{k,#/2}   (* Iterate from k=1 to #/2 *)
      Range[#][[            ]]                 (* From {1..#}, take... *)
                      {k,-k}                   (* k-th and negative k-th element *)
                                               (* negative k-th = k-th from the end *)
                (-1)^k                         (* Reversed for odd k *)
Join@@                                         (* Join the result *)

```

# Answer
> 2 votes
# Python 2, 64 63 bytes

 -1 byte thanks to ovs!

```
lambda n:sum([[i,i+1,n-i,n+~i]for i in range(1,n/2,2)],[n])[:n]

```

Try it online!

# Answer
> 2 votes
# Bash + Perl + Groff + Psutils, 48 bytes

```
perl -nE'say".bp
"x--$_'|groff|psbook>/dev/null

```

Shows output on `stderr`. Output contains some trailing garbage.

Example of use:

```
$ echo 20 | perl -nE'say".bp
> "x--$_'|groff|psbook>/dev/null
[20] [1] [2] [19] [18] [3] [4] [17] [16] [5] [6] [15] [14] [7] [8] [13] [12]
[9] [10] [11] Wrote 20 pages, 4787 bytes

```

# Answer
> 2 votes
# Java 8, ~~84~~ 72 bytes

```
n->{for(int j=0;++j<n;System.out.printf("%d,%d,%d,%d,",n--,j++,j,n--));}

```

or

```
n->{for(int j=0;++j<n;System.out.print(n--+","+j+++","+j+","+n--+","));}

```

-12 bytes thanks to *@TheLethalCoder*'s comment on the C# answer.

**Old answer (84 bytes):**

```
n->{int r[]=new int[n],i=1,N=n,J=1;for(r[0]=n;i<n;r[i]=-~i++%4<2?J++:--N);return r;}

```

**Explanation:**

Try it here.

```
n->{                  // Method with integer parameter and no return-type
  for(int j=0;++j<n;  //  Loop from 1 to `n` (exclusive)
    System.out.printf("%d,%d,%d,%d,",n--,j++,j,n--)
                      //   Print four numbers simultaneously
  );                  //  End of loop
}                     // End of method

```

# Answer
> 2 votes
## Haskell, 42 bytes

```
n#a|n<a=[]|x<-n-2=n:a:a+1:n-1:x#(a+2)
(#1)

```

Try it online!

One byte longer:

### Haskell, 43 bytes

```
f n=[1,3..div n 2]>>= \x->[n-x+1,x,x+1,n-x]

```

# Answer
> 1 votes
# , ~~64~~ 60 bytes

Devastatingly outgolfed by djhurio! His answer is quite elegant, go upvote it.

```
n=scan();matrix(c(n-(k=seq(1,n/2,2))+1,k,k+1,n-k),4,,T)[1:n]

```

A port of rayryeng's Octave answer.

Try it online!

### original solution (64 bytes):

```
f=function(n,l=1:n)`if`(n,c(l[i<-c(n,1,2,n-1)],f(n-4,l[-i])),{})

```

Recursive function.

Try it online!

# Answer
> 1 votes
# Perl 5, 47 + 1 (-n) = 48 bytes

```
$,=$";print$_--,$i+++1,$i+++1,$_--,''while$_>$i

```

Try it online!

# Answer
> 1 votes
# Swift 3, 74 bytes

```
func g(f:Int){for i in stride(from:1,to:f/2,by:2){print(f-i+1,i,i+1,f-i)}}

```

**Try it online!**

# Swift 3, 60 bytes

```
{f in stride(from:1,to:f/2,by:2).map{(f-$0+1,$0,$0+1,f-$0)}}

```

For some reason, this does not work in any online environment I have tried so far. If you want to test it, put `var g=` in front of it, and call it with `print(g(12))` in Xcode (Playgrounds).

Here is a picture after I've ran it in an Xcode playground, version 8.3.1 (Running Swift 3.1):

# Answer
> 1 votes
# QBIC, 25 bytes

```
[1,:/2,2|?b-a+1,a,1+a,b-a

```

Although the input is %4, the actual rhythm is 2-based.

## Explanation

```
[1,:/2,2|   FOR ( b=1; b <= <input>/2; b=b+2)
?           PRINT
 b-a+1,     n
 a,         1
 1+a,       2
 b-a        n-1

```

# Answer
> 1 votes
# Python 2, 50 bytes

A port of Arnauld's JS answer.

```
f=lambda n,k=1:n>k and[n,k,k+1,n-1]+f(n-2,k+2)or[]

```

Try it online!

# Answer
> 1 votes
# C (gcc), 66 bytes

A port of my Octave answer to C (gcc):

```
f(n,i){for(i=1;i<n/2;i+=2)printf("%d %d %d %d ",n-i+1,i,i+1,n-i);}

```

Try it online!

# Answer
> 1 votes
# cQuents, 21 bytes

```
=n::n-z+1,z+1,x-1,z-1

```

Try it online!

## Explanation

```
                            Implicit input n
=n                          First item in the sequence is n
  ::                        Mode :: (Sequence 2): print sequence from 1 to n
                            Comma delimited items are rotated through
    n-z+1,                    n - previous + 1
          z+1,                previous + 1
              x-1,            third-previous - 1
                  z-1         previous - 1

```

# Answer
> 0 votes
# Pyth, ~~27~~ ~~24~~ 23 bytes

-3 bytes by printing throughout instead of at the end.

-1 Thanks to Mr. Xcoder

```
V:1/Q2 2pjd[-QtNNhN-QNk

```

Try it online!

Or on the online Compiler/Executor

This is my first real program in Pyth, so there's probably better methods that I don't know about.

# Explanation

```
V:1/Q2 2pjd[-QtNNhN-QNk
V:1/Q2 2                   # For N in range(1, Q/2, 2):
        pjd                # print " ".join(...),
           [-QtNNhN-QNk    # The list [n - (N-1), N, N + 1, n - N, ""] (n is input)

```

# Answer
> 0 votes
# Pyth, ~~21~~ 20 bytes

```
sm[hK-QddhdK):1/Q2 2

```

**Test Suite.**

If outputting as a nested list is allowed:

# Pyth, ~~20~~ 19 bytes

```
m[hK-QddhdK):1/Q2 2

```

**Test Suite.**

---

# Explanation

```
sm[hK-QddhdK):1/Q2 2  - Full program.

 m           :1/Q2 2  - Map over range(1,input()/2,2) with a variable d.
  [         )         - Construct a list with:
   hK-Qd                - Input - d + 1,
        d               - d,
         hd             - d + 1 and
           K            - Input - d.
s                     - Flattens the list and prints implicitly.

```

# Answer
> 0 votes
# Ruby, 40 bytes

```
->n{1.step(n/2,2){|x|p n-x+1,x,x+1,n-x}}

```

Try it online!

# Answer
> 0 votes
## C#, 107 bytes

```
int[]F(int p){var a=new int[p];for(int i=0,q=1;q<p;a[i++]=p--){a[i++]=p--;a[i++]=q++;a[i++]=q++;}return a;}

```

Keep two counters, one starting at 1, one at p. In each loop iteration, write four elements and just increment or decrement counters after each entry. When the counters meet in the middle, stop.

```
int[] F(int p)
{
    var a = new int[p];
    for(int i = 0, q = 1; q < p; a[i++] = p--)
    {
        a[i++] = p--;
        a[i++] = q++;
        a[i++] = q++;
    }
    return a;
}

```

# Answer
> 0 votes
# Haskell, 58 bytes

```
(x:y:r)#(a:b:s)=x:y:a:b:r#s
f n=take n$n:[1..]#[n-1,n-2..]

```

Try it online!

# Answer
> 0 votes
# C++ (gcc), ~~89~~ ~~84~~ 68 bytes

As unnamed generic lambda. `n` is #pages (%4==0) and `C` is a reference parameter for the result, an empty container like `vector<int>` (only `push_back` is needed).

```
[](int n,auto&C){for(int i=0,j=0;i<n;C.push_back(++j%4<2?n--:++i));}

```

previous solution:

```
#define P C.push_back(
[](int n,auto&C){for(int i=0;i<n;P n--),P++i),P++i),P n--));}

```

Try it online!

Slightly ungolfed:

```
auto f=
[](int n,auto&C){
 for(int i=0,j=0;
     i<n;
     C.push_back(++j%4<2 ? n-- : ++i));
}

```

previous solution slightly ungolfed:

```
auto f=
[](int n, auto&C){
 for(
  int i=0;
  i<n;
   P n--),
   P++i),
   P++i),
   P n--)
 );
}
;

```

It was quite straightforward developed and there are sure some minor optimizations in the arithmetics.

* Edit1: unification of the arithmetics saved 5 byte
* Edit2: after the unification the 4 steps were combined

Usage:

```
std::vector<int> result;
f(n, result);

```

### Print-Variant, 77 bytes out-dated

If you insist on printing the values, there is this solution:

```
[](int n,auto&o){for(int i=0;i<n;o<<n--<<' '<<++i<<' '<<++i<<' '<<n--<<' ');}

```

Where `o` is your desired `std::ostream`, like `std::cout`

Usage (if 2nd lambda was assigned to `g`):

```
g(n, std::cout);

```

# Answer
> 0 votes
# Common Lisp, 79 bytes

```
(defun f(n &optional(k 1))(and(> n k)`(,n,k,(1+ k),(1- n),@(f(- n 2)(+ k 2)))))

```

Try it online!

# Answer
> 0 votes
## Lua, 94 bytes

For this challenge I actually came up with 2 different methods that are both 94 bytes.

**Method 1:**

```
function f(n,i)i=i or 1 return n>i and('%s,%s,%s,%s,%s'):format(n,i,i+1,n-1,f(n-2,i+2))or''end

```

**Commented Code:**

```
function f(n,i)
  i=i or 1
  -- On the first iteration i will be nil so I'm setting it's value to 1 if it is.

  return n>i and ('%s,%s,%s,%s,%s'):format(n,i,i+1,n-1,f(n-2,i+2)) or ''
  -- Here i return a ternary statement
  -- If n>i is true, it will return a string using string.format() and part of this is recursion
  -- If it's false, it will just return an empty string
end

```

**Method 2:**

```
function f(n,i)i=i or 1 return n>i and n..','..i..','..i+1 ..','..n-1 ..','..f(n-2,i+2)or''end

```

This method is similar to the first method however I'm instead returning a concatenated string instead of string.format()

In both methods I have used the concept of n and i getting closer together

# Answer
> 0 votes
# PHP, 51+1 bytes

```
while($i<$k=&$argn)echo$k--,_,++$i,_,++$i,_,$k--,_;

```

prints page numbers separated by underscore with a trailing delimiter.
Run as pipe with `-nR` or try it online.

# Answer
> 0 votes
# , 22 bytes

```
($,)_2|.`]\1+],@,.&i.-

```

Try it online!

## Explanation

```
($,)_2|.`]\1+],@,.&i.-  Input: integer n
             ]          Identity
                     -  Negate
                  &i.   Form the ranges [0, 1, ..., n-1] and [n-1, ..., 1, 0]
                ,.      Interleave
              ,@        Flatten
           1+           Add 1
    _2    \             For each non-overlapping sublist of size 2
        `                 Cycle between these two operations
      |.                    Reverse for the first, third, ...
         ]                  Identity for the second, fourth, ...
  ,                     Flatten
 $                      Reshape to length n

```

---
Tags: code-golf, sequence
---


title: Ascii User Interfaces

text:
# Question
Title: Ascii User Interfaces
In this challenge, we render Ascii user interfaces.

```
+----------------------+
|+-----------++-------+|
||<- Previous||Next ->||
|+-----------++-------+|
|== The title ==       |
|                      |
|Lorem ipsum dolor     |
|sit amet...           |
|+--------------+      |
||Post a comment|      |
|+--------------+      |
|+-----------------+   |
||User X commented:|   |
||                 |   |
||This is amazing! |   |
|+-----------------+   |
|+-----------------+   |
||User Y commented:|   |
||                 |   |
||lol              |   |
|+-----------------+   |
+----------------------+

```

Each drawing like this is made of one *element*, which can contain subelements. The possible elements are listed below:

1. Text element. Contains one or more lines of text.
2. Box element. Contains one subelement that is surrounded with borders. The borders have `+`s at the corners and `-`s and `|` at the edges.
3. Horizontal list. Contains one or more elements that are aligned horizontally.
4. Vertical list. Contains one or more elements that are aligned over each other vertically and to left horizontally.

Every element is a rectangle.

Each element, in addition to its content, has a property called *baseline*. The baseline is used to align the elements vertically: every element of a horizontal list is aligned such that their baselines are on the same line. In the example below, the baseline contain characters `aeg`. The baselines of the three box elements are (0-indexed) `1`, `3` and `2`.

```
   +-+
   |c|+-+
+-+|d||f|
|a||e||g|
|b|+-+|h|
+-+   +-+

```

The baselines are determined with the following rules:

1. For text elements, the first line of text is the baseline, ie. `0`.
2. For box elements, the baseline is 1 + the baseline of the subelement.
3. For horizontal lists, the baseline is the maximum baseline in the list (`3` in the example above).
4. For vertical lists, the baseline is the baseline of an element, which must be specified in the input.

## Input

The input is a specification of an interface in some format (eg. lists, json). The example inputs have the following format:

1. A string element is a string: `"..."`
2. A box element is a list thats first element is `"b"`: `["b", subelement]`
3. A horizontal list is a list thats first element is `"h"`: `["h", items...]`
4. A vertical list is a list thats first element is `"v"` and the second element is the (0-indexed) number of the element thats baseline is used: `["v", n, items...]`

## Output

The output must contain the elements aligned using the rules I specified above. The output can be stdout, a list of strings or anything else meaningful.

## Scoring

This is , the usual rules apply.

## Test cases

1

```
["b", ["v", 0, ["h", ["b", "<- Previous"], ["b", "Next ->"]], "== The title ==\n\nLorem ipsum dolor\nsit amet...", ["b", "Post a comment"], ["b", "User X commented:\n\nThis is amazing!"], ["b", "User Y commented:\n\nlol"]]]

+----------------------+
|+-----------++-------+|
||<- Previous||Next ->||
|+-----------++-------+|
|== The title ==       |
|                      |
|Lorem ipsum dolor     |
|sit amet...           |
|+--------------+      |
||Post a comment|      |
|+--------------+      |
|+-----------------+   |
||User X commented:|   |
||                 |   |
||This is amazing! |   |
|+-----------------+   |
|+-----------------+   |
||User Y commented:|   |
||                 |   |
||lol              |   |
|+-----------------+   |
+----------------------+

```

2

```
["h", ["b", ["v", 0, "a", "b"]], ["b", ["v", 2, "c", "d", "e"]], ["b", ["v", 1, "f", "g", "h"]]]

   +-+
   |c|+-+
+-+|d||f|
|a||e||g|
|b|+-+|h|
+-+   +-+

```

3

```
["h", ["b", ["v", 0, ["b", ["h", "a\nb", "c"]], "d", "e", ["h", ["h", "f"], ["b", ["h", "g"]], "h"]]], ["b", "ijk\nl\nmn\no"], ["v", 2, ["b", "pqrst"], ["b", "uv\nw"], ["b", "x"]], ["b", ["b", ["b", "yz"]]]]

            +-----+
            |pqrst|
            +-----+
            +--+
            |uv|
            |w |   +------+
+-----+     +--+   |+----+|
|+--+ |+---++-+    ||+--+||
||ac| ||ijk||x|    |||yz|||
||b | ||l  |+-+    ||+--+||
|+--+ ||mn |       |+----+|
|d    ||o  |       +------+
|e    |+---+
| +-+ |
|f|g|h|
| +-+ |
+-----+

```

4

```
["h", "a * b = ", ["v", 0, "a + a + ... + a", "\\_____________/", "    b times"]]

a * b = a + a + ... + a
        \_____________/
            b times

```

# Answer
# Python 3, 721 694 693 671 661 bytes

**Edit:** Saved 27 bytes due to @Arnold Palmer and @Step Hen

**Edit:** Saved 1 byte

**Edit:** Saved 22 bytes thanks to @Arnold Palmer

**Edit:** Saved 10 bytes

This could probably be golfed quite a bit

```
L,M,R,e=len,max,range,lambda t:([list(r)+[" "]*(M(map(L,t.split("\n")))-L(r))for r in t.split("\n")],0)if str==type(t)else b(t)if"h">t[0]else h(t)if"v">t[0]else v(t);F=lambda t:"\n".join(map("".join,e(t)[0]))
def h(t):
	t=[e(r)for r in t[1:]];Z=M(s[1]for s in t);X=M(L(s[0])-s[1]for s in t)+Z;u=[[]for i in R(X)]
	for a,b in t:u=[u[j]+[Z-b<=j<L(a)+Z-b and a[j-Z+b][i]or" "for i in R(L(a[0]))]for j in R(X)]
	return u,Z
def b(t):t,b=e(t[1]);u=[["+",*"-"*L(t[0]),"+"]];return u+[["|"]+r+["|"]for r in t]+u,1+b
def v(t):w=[e(r)for r in t[2:]];return[a[i]+[" "]*(M(L(a[0])for a,d in w)-L(a[i]))for a,c in w for i in R(L(a))],sum(L(x[0])for x in w[:t[1]])+w[t[1]][1]

```

Try it online
> 10 votes

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