title: The meeker number sequence

text:
# Question
Title: The meeker number sequence
The Meeker numbers are a 7 digit number in form of \\$abcdefg\\$, where \\$a×b=10c+d\\$ and \\$d×e=10f+g\\$. As an example \\$6742612\\$ is a meeker number, here \\$6×7=10×4+2\\$ and \\$2×6=10×1+2\\$, so it is a meeker number.

Additionally, a Meeker number does not have any leading zeros (so \\$a \ne 0\\$)

## The Challenge

Your program can do one of the following tasks:

* Take a positive integer \\$n\\$ and output the \\$n\\$th Meeker number (0 or 1 indexed, your choice. If 0 indexed, \\$n\\$ will be a non-negative integer)
* Take a positive integer \\$n\\$ and output the first \\$n\\$ Meeker numbers
* Output all 900 Meeker numbers

# Rules

* You may take an empty input if you output all Meeker numbers
* Standard loopholes are forbidden.
* Trailing whitespace is allowed.
* If possible, please link to an online interpreter (e.g. TIO) to run your program on.
* Please explain your answer. This is not necessary, but it makes it easier for others to understand.
* Languages newer than the question are allowed. This means you could create your own language where the empty program calculates this number, but don't expect any upvotes.
* This is , so shortest code in bytes wins!

The first few Meeker numbers are

```
1000000
1000100
1000200
1000300
1000400
1000500
1000600
1000700
1000800
1000900
1101000
1101101
1101202
1101303
1101404
1101505
1101606
1101707
1101808
1101909
...

```

*Thanks to @Adám for the detailed analysis and @cairdcoinheringaahing for the editing rework*

# Answer
# APL (Dyalog Extended), 45 bytes (SBCS)

Full program. Prints all meeker numbers. Requires 0-based indexing (`⎕IO←0`).

```
1e6+⍸{(×⌿i⊇⍵)≡10⊥⍵[2+i←0 1,⍪3 4]}¨10⊤¨1e6…1e7

```

Try it online! (limited to upper bound of 2 000 000 ― above code works offline)

`1e6…1e7` numbers 1 000 000 through 10 000 000

`10⊤¨` base-10 representation of each (splits digits of numbers into lists of digits)

`{` apply the following lambda to each:

`⍵[``]` index the digits of the current number using the following:

`⍪3 4` the column-vector `[[3],[4]]`

`0 1,` prepend a column consisting of `[0,1]` yielding `[[0,3],[1,4]]`

`i←` assign to `i` (for **i**ndices)

`2+` increase by two; `[[2,5],[3,6]]`

`10⊥` evaluate as base-10, using the top row as tens place and bottom row as ones place

`(``)≡` check if it matches the following:

`i⊇⍵` select the elements from the digits at indices `i`

`×⌿` multiply the elements of the top row with the elements of the bottom row

**ɩ**ndices where true

`1e6+` offset to the first candidate
> 6 votes

# Answer
# Python 2, ~~121~~ ~~115~~ 98 bytes

```
def f(n,t=10):p,q=n%100/t,1+n/100;r=p*q;s=n%t*(r%t);print`t+n/t`+'0'*(r<t)+`r`+`n%t`+'0'*(s<t)+`s`

```

Try it online!

On noticing the digits, I observed a pattern and got this constant time solution. Takes n as input (0-indexed) and prints n'th meeker number.

For example, the first 2 digits follow the pattern: 10, 11, 12, ... 99 (with each number occuring 10 times in a row).

*thanks to ovs for -23 bytes*
> 6 votes

# Answer
# C (gcc), ~~107~~ \\$\cdots\\$ ~~74~~ 73 bytes

Saved 8 bytes thanks to the man himself Arnauld!!!
Saved 5 bytes thanks to tsh!!!
Saved a whopping 20 bytes thanks to Olivier Grégoire!!!

```
t=10;h=100;a;b;f(n){a=n/h+1;b=n/t%t;a=(a*t*h+b*h+a*b)*t*h+n%t*(h+a*b%t);}

```

Try it online!

Inputs \\$0\\$-based \\$n\\$ and returns the \\$n^{\text{th}}\\$ Meeker number.
> 6 votes

# Answer
# JavaScript (SpiderMonkey), 65 bytes

```
for(i=99;i<999;print((e-i+'0'-a*b+e)*~99+a*b%10*e))[a,b,e]=++i+''

```

Try it online!

For example, when `i == 267`:

```
i=267;
[a,b,e]=i+'';
print([a, b, e]); // ["2", "6", "7"]
print(e-i); // -260
print(e-i+'0'); // "-2600"
print(a*b); // 12
print(e-i+'0'-a*b); // -2612
print(e-i+'0'-a*b+e); // "-26127"
print((e-i+'0'-a*b+e)*~99); // 2612700
print((e-i+'0'-a*b+e)*~99+a*b%10*e); // 2612714

```

Try it online!

---

# JavaScript (Firefox), 72 bytes

```
for(f='%.2d',i=99;i<999;console.log(a+b+f+e+f,a*=b,a%10*e))[a,b,e]=++i+f

```

Thanks Neil for pointing out that Firefox support `%.2d` for padding zeros.
> 5 votes

# Answer
# , ~~101~~ ~~91~~ ~~71~~ 69 bytes

*Edit: -2 bytes thanks to Giuseppe, amazingly within \<5 mins of posting*

```
outer(10:99,0:9,function(a,e,d=a%%10)((a*100+a%/%10*d)*10+e)*100+d*e)

```

Try it online!

---

The original version - inspired by and taking a similar approach to Manish Kundu's answer, and also golfed-down from 101 to 96 bytes by Giuseppe:

# , 96 bytes

```
z=c(0,'')
paste0(a<-100:999%/%100,b<-0:99%/%10,z[(a*b>9)+1],d<-a*b,0:9,z[((f=d%%10*0:9)>9)+1],f)

```

Try it online!

(Note on `z=c(0,'')`: we need to 'pad' the single digit products with a zero when building our text string, and this needs to be done in way that's compatible with the vectorized `paste` function. So `z[(a*b>9)+1]` is equivalent to (but shorter than) `ifelse(a*b>9,'',0)`)
> 5 votes

# Answer
# Husk, 27 bytes

```
föΛo§=oΠ←od→C2§e←→X4dfo=7LN

```

Try it online!

returns the list of all meeker numbers. It's horribly inefficient, so here's a version which starts from 1e7, and shows the first n values.

**EDIT:** corrected the answer after Dominic Van Essen found a bug.
> 4 votes

# Answer
# Perl 5, ~~58~~ 56 bytes

```
/(.)(.)(.(.))(.)/,$1*$2-$3||$5*$4-$'||say for 1e6..1e7-1

```

Try it online!

Outputs the entire list of Meeker numbers.
> 4 votes

# Answer
# 05AB1E, ~~32~~ 24 bytes

```
θsт+2£DSPsт*+ìD2.£SPsт*+

```

Try it online! Outputs the \\$n^\text{th}\\$ Meeker number.
> 4 votes

# Answer
# JavaScript (Node.js), 86 bytes

```
_=>[...Array(1e7).keys()].filter(x=>(s=x+'')[0]*s[1]==s[2]+s[3]&&s[3]*s[4]==s[5]+s[6])

```

Try it online!

I feel like this is too long.

# Explanation

Basically, this gets all numbers from 0 to 9999999, coerces each to a string and checks character-wise.

One of Javascript's quirks is that multiplied strings are coerced to numbers, but added ones are not. So `'5'*'6'` is 30, but `'5'+'6'` is 56.

So in `s[0]*s[1]==s[2]+s[3]`, the first half is a number which is the product of the first two, the second half is the two cocatenated into a string, and using == allows type conversion.

Since it gets the numbers from 0 to 9999999, the numbers from 0 to 999999 are invalid and shouldn't be counted. Fortunately, since the number is coerced to a string, taking its 6th (0-indexed) character will return undefined, so it will be counted as invalid.
> 3 votes

# Answer
# Haskell, ~~82~~ ~~80~~ 76 bytes

* -6 bytes thanks to kops, for rearranging things and proposing a better interpretation of the rules :P

```
[n|n<-show<$>[1..],[a,b,c,d,e,f,g]<-[read.pure<$>n],a*b==10*c+d,d*e==10*f+g]

```

Try it online!

The list of all Meeker numbers, represented as strings.

# Haskell, 80 bytes

```
[n>>=show|n@[a,b,c,d,e,f,g]<-mapM([0..9]<$id)[1..7],a>0,a*b==10*c+d,d*e==10*f+g]

```

Try it online!
> 3 votes

# Answer
# Jelly,  ~~20~~  19 bytes

-1 thanks to Makonede (Output first \\$n\\$ instead of the \\$n^\text{th}\\$.)

```
DḌ,PƊƝFḊm3⁼2/Ạ
ȷ6Ç#

```

A monadic Link accepting an integer, \\$n\in\[1,900\]\\$, that yields the first \\$n\\$ Meeker numbers

**Try it online!** Very slow so will probably time out for \\$n \gt 36\\$.

### How?

```
ȷ6Ç# - Main Link: integer, n
ȷ6   - 10^6
   # - find the first n integers starting at 10^6 for which:
  Ç  -   call Link 1

DḌ,PƊƝFḊm3⁼2/Ạ - Link 1: integer, x   e.g. 9218756
D              - digits (x)                [9,2,1,8,7,5,6]
     Ɲ         - for neighbours:
    Ɗ          -   last three links as a monad f([a,b]):
 Ḍ             -     from digits ([a,b])   [92, 21, 18, 87, 75, 56]
   P           -     product ([a,b])       [18, 2,  8, 56, 35, 30]
  ,            -     pair                  [[92, 18], [21, 2], [18, 8], [87, 56], [75, 35], [56, 30]]
      F        - flatten                   [92, 18, 21, 2, 18, 8, 87, 56, 75, 35, 56, 30]
       Ḋ       - dequeue                   [18, 21, 2, 18, 8, 87, 56, 75, 35, 56, 30]
        m3     - modulo-3-slice            [18,        18,        56,         56]
           2/  - pairwise reduce by:
          ⁼    -   equal?                  [1,1]
             Ạ - all?                      1

```
> 3 votes

# Answer
# Husk, ~~34~~ ~~31~~ 30 bytes

```
₁`:%10¹d₁↑2d+100
§+o*100doΠ↑_2

```

Try it online! or Get the whole meeker sequence

*Calculates* (rather than brute-forcing) the `n`th meeker number.

Not as short as Razetime's answer, but inspired by A username's comment "I wonder if anyone isn't going to brute-force it..." underneath it.

A nice feature of this approach is that it actually completes the task, although there were obviously never any brownie-points on offer for achieving this questionable goal…

**How?**

```
§+o*100doΠ↑_2      # helper function (₁):
                   # takes a list of digits, and returns the number formed
                   # by appending the product of the last 2 digits.
§+                 # Add together
        oΠ         #  product of
          ↑_2      #  last 2 digits, and
  o*100            #  100x
       d           #  the number represented by the digits

₁`:%10¹d₁↑2d+100   # main program:
            +100   # add 100 to the input,
           d       # get the digits,
        ₁↑2        # apply helper function ₁ to the first 2 digits,
       d           # and convert this back into a list of digits;
 `:                # now append with
   %10¹            # the input modulo 10 = last digit of input;
₁                  # finally apply helper function ₁ to the result

```
> 3 votes

# Answer
# Java (JDK), 75 bytes

```
n->{int a=n/100+1,b=n/10%10;return(a*1e3+b*100+a*b)*1e3+n%10*(100+a*b%10);}

```

Try it online!

Outputs the nth number, 0-indexed.

## Credits
> 3 votes

# Answer
# Charcoal, 33 bytes

```
Ｆ…χ¹⁰⁰Ｆχ⟦⪫⟦ι﹪%02dΠικ﹪%02d×﹪Πιχκ⟧ω

```

Try it online! Link is to verbose version of code. Prints all 900 Meeker numbers. Explanation:

```
Ｆ…χ¹⁰⁰

```

Loop over all possible first pairs of digits.

```
Ｆχ

```

Loop over all possible fifth digits.

```
⟦⪫⟦...⟧ω

```

Print the following items on one line and then move to the next line.

```
ι

```

The first two digits.

```
﹪%02dΠι

```

The product of the first two digits, left zero-padded to 2 digits.

```
κ

```

The fifth digit.

```
﹪%02d×﹪Πιχκ

```

The last two digits.
> 2 votes

# Answer
# Pyth, 58 bytes

```
A(/%Q100T+1/Q100)A(*GH*%*GHT%QT)s[+T/QT*"0"<GTG%QT*"0"<HTH

```

Try it online!

Same as my Python solution. `A` assigns the two provided elements to the variables `G` and `H` respectively. `Q` is the input (zero-indexed).
> 2 votes

# Answer
# Scala, 103 bytes

```
Stream from 1 map "".+filter{x=>x.size==7&&x.map(_-48).sliding(4,3).forall{x=>x(0)*x(1)==10*x(2)+x(3)}}

```

Try it in Scastie!

A pretty straightforward answer. You can treat it like a function giving the nth Meeker number (0-indexed) or as a list of all Meeker numbers.
> 2 votes

# Answer
# Retina, 65 bytes

```

999*¶

$.`
G`...

;
+`(.);(.)
$1$2,0$.($1*$2*
;|,0?(?=...,|..;)

```

Try it online! Outputs all 900 Meeker numbers. Explanation:

```

999*¶

$.`

```

Insert all the numbers from `0` to `999`.

```
G`...

```

Keep only the 3-digit numbers.

```
;

```

Insert separators around all of the digits.

```
+`(.);(.)
$1$2,0$.($1*$2*

```

Multiply the first and second digits, then multiply the last digit of the result by the third digit, inserting an extra `0` prefix for each result.

```
;|,0?(?=...,|..;)

```

Delete unnecessary separators and `0`s.
> 1 votes

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


title: LCM of Rational Numbers

text:
# Question
Title: LCM of Rational Numbers
The least common multiple (LCM) of a set of numbers `A` is the smallest integer `b` such that `b/a` is an integer for all integers `a` in `A`. This definition can be extended to rational numbers!

# Task

Find the smallest positive **rational** `b` such that `b/a` is an **integer** for all **rationals** `a` in the input.

# Rules

* Standard loopholes are forbidden.
* You may take numerators and denominators separately in the input, but may not take doubles, floats, etc.
* The input may not be fully reduced.
* You may take integer inputs as rationals with denominator of `1`.
* Submissions that would feed rational numbers to an LCM/GCD builtin are allowed, but non-competing.

# Test Cases

```
In:  3
Out: 3

In:  1/17
Out: 1/17

In:  1/2, 3/4
Out: 3/2

In:  1/3, 2/8
Out: 1

In:  1/4, 3
Out: 3

In:  2/5, 3
Out: 6

In:  1/2, 3/4, 5/6, 7/8
Out: 105/2

```

This is , so submissions using the fewest bytes win!

# Answer
# Jelly, 19 bytes

```
g/:@$€Z©Ḣæl/;®Ḣg/$¤

```

Try it online!
> 5 votes

# Answer
# J, 3 bytes

```
*./

```

Given a list of rational inputs, this folds LCM through it.
> 7 votes

# Answer
# Jelly, 12 bytes

```
:g/æl/;g/}ɗ/

```

Try it online!

Takes input as `[[list of numerators], [list of denominators]]`. +2 bytes to take input as a list of `[numerator, denominator]` pairs

## How it works

```
:g/æl/;g/}ɗ/ - Main link. Takes a pair of lists [N, D] on the left
  /          - Columnwise reduce by:
 g           -   GCD
:            - Divide, reducing the fractions to their simplest form
          ɗ  - Group the previous 3 links into a dyad f(N, D):
   æl/       -   LCM of N
         }   -   To D:
       g/    -     GCD
      ;      -   Concatenate
           / - Reduce; Yield f(N, D) where N is the first list and D the second

```

The 14 byte version transposes the input with `Z` to get it into the `[N, D]` format, then uses `$` as a "grouping" construct the make the `:g/` act on that
> 5 votes

# Answer
# Python 2, 65 bytes

```
lambda x:reduce(lambda x,y:x*y/gcd(x,y),x)
from fractions import*

```

Try it online!
> 4 votes

# Answer
# sed, 374 (373+1) bytes

sed's `-E` flag counts as one byte. Note: I haven't tried to golf this yet, and probably won't for quite some time.
Input is taken in unary, and output is in unary. Spaces must surround every fraction. Example: `echo " 1/111 111/11111 111111/111 "`.

```
:d;s, (1*)/\1(1*), \1/\22,;s,(1*)(1*)/\2 ,2\1/\2 ,;td;s,1*(1/22*),\1,g;s,(22*/1)1*,\1,g;:r;s,((1*)/1*)2,\1\2,;s,2(1*/(1*)),\2\1,;tr;h;s,1*/,,g;:g;s/^(1*) 1(1*) 1(1*)/1\1 \2 \3/;tg;s/  */ /g;s/^/ /;/1 1/bg;x;s,/1*,,g;s/^( 1*)( 1*)/\1\2\2/;:l;s/^(1*) (1*) \2(1*)/\1\2 \2 \3/;tl;/  $/be;/  /{s/^(1*) 1*  1*( 1*)/ \1\2\2/;bl};s/^(1* 1* )(1*) (1*)/\1\2\3 \3/;bl;:e;G;s, *\n *,/,

```

Try it online!
> 4 votes

# Answer
# Pari/GP, 30 bytes

This only apply the `lcm` built-in on integers.

```
a->d=denominator(a);lcm(a*d)/d

```

Try it online!

---

# Pari/GP, 3 bytes

This feeds rational numbers to the `lcm` built-in, so it is non-competing.

```
lcm

```

Try it online!
> 3 votes

# Answer
## JavaScript (ES6), 85 bytes

```
a=>a.reduce(([b,c],[d,e,g=(b,c)=>c?g(c,b%c):b,h=g(b*e,c*d),i=g(b*d,h)])=>[b*d/i,h/i])

```

Look no builtins! No doubt someone will beat this using a recursive approach or something.
> 3 votes

# Answer
# Common Lisp, 154 bytes

```
(defun f(l &aux(s(pairlis l l)))(loop(and(eval`(=,@(mapcar'car s)))(return(caar s)))(let((x(assoc(reduce'min s :key'car)s)))(rplaca x(+(car x)(cdr x))))))

```

Algorithm used (specified for integers, but works also for rationals).

First make an associative list of the input data with itself, to get track of the initial values of the elements, so the operating sequence is given by the “car”s of the list.

```
(defun f(l &aux (s (pairlis l l)))        ; make the associative list
  (loop
     (when (eval `(= ,@(mapcar 'car s))) ; when the car are all equal
       (return (caar s)))                 ; exit with the first one
     (let ((x (assoc (reduce 'min s :key 'car) s))) ; find the (first) least element
       (rplaca x (+ (car x) (cdr x))))))  ; replace its car adding the original value (cdr)

```

Test cases:

```
CL-USER> (f '(3))
3
CL-USER> (f '(1/17))
1/17
CL-USER> (f '(1/2 3/4))
3/2
CL-USER> (f '(1/3 2/8))
1
CL-USER> (f '(1/4 3))
3
CL-USER> (f '(2/5 3))
6
CL-USER> (f '(1/2 3/4 5/6 7/8))
105/2

```

Note: The solution is without the use of the builting `lcm` and `gcd`, that accept integers.
> 2 votes

# Answer
# Perl 6,  ~~46~~  42 bytes

```
{[lcm](@_».numerator)/[gcd] @_».denominator}

```

test it

```
{[lcm](($/=@_».nude)[*;0])/[gcd] $/[*;1]}

```

test it

Input is a list of Rational numbers.

## Expanded:

```
{ # bare block lambda with implicit parameter list ｢@_｣

  [lcm](            # reduce using &infix:<lcm>
    (
      $/ = @_».nude # store in ｢$/｣ a list of the NUmerators and DEnominiators
                    # ((1,2), (3,4))

    )[
      *;            # from all of the first level ｢*｣,
      0             # but only the 0th of the second level (numerators)
    ]
  )
  /
  [gcd] $/[ *; 1 ]  # gcd of the denominators
}

```
> 2 votes

# Answer
# Retina, 117 bytes

```
\d+
$*
\b(1+)(\1)*/(\1)+\b
$#2$*11/$#3$*
{`^((1+)\2*)/(1+)+ (\2)+/\3+\b
$1 $#4$*1/$3
}`\G1(?=1* (1+))|\G 1+
$1
1+
$.&

```

Try it online! Takes input as a space-separated series of improper fractions (no integers or mixed numbers). Explanation:

```
\d+
$*

```

Converts decimal to unary.

```
\b(1+)(\1)*/(\1)+\b
$#2$*11/$#3$*

```

This reduces each fraction to its lowest terms. Capture group 1 represents the GCD of the numerator and denominator, so we count the number of captures before and after the `/`. `\b(1+)+/(\1)+\b` doesn't seem to count the number of captures correctly for some reason, so I use an extra capturing group and add 1 to the result.

```
{`^((1+)\2*)/(1+)+ (\2)+/\3+\b
$1 $#4$*1/$3

```

This does a number of things. Capture group 2 represents the GCD of the numerators of the first two fractions, while capture group 3 represents the GCD of the denominators. `$#4` is therefore the second numerator divided by their GCD. (Again, I couldn't could the number of captures of the first numerator, but I only need to divide one numerator by their GCD, so it doesn't cost me quite so much.)

```
}`\G1(?=1* (1+))|\G 1+
$1

```

Now that the second numerator has been divided by their GCD, we just use this expression from the unary arithmetic tutorial to multiply the two together, resulting in the LCM. We then repeat the exercise for any remaining fractions.

```
1+
$.&

```

Converts unary back to decimal.
> 2 votes

# Answer
# Mathematica, 3 bytes

```
LCM

```

Mathematica's built-in `LCM` function is capable of handling rational number inputs.
> 1 votes

# Answer
# PHP, 194 bytes

```
<?for(list($n,$d)=$_GET,$p=array_product($d);$x=$n[+$k];)$r[]=$x*$p/$d[+$k++];for($l=1;$l&&++$i;$l=!$l)foreach($r as$v)$l*=$i%$v<1;for($t=1+$i;$p%--$t||$i%$t;);echo$p/$t>1?$i/$t."/".$p/$t:$i/$t;

```

-4 Bytes with PHP\>=7.1 `[$n,$d]=$_GET` instead of `list($n,$d)=$_GET`

Try it online!
> 1 votes

# Answer
## Common Lisp, ~~87~~ 78 bytes

Using `lcm` and `gcd`, which have integer inputs:

```
(defun l(a)(/(apply #'lcm(mapcar #'numerator a))(apply #'gcd(mapcar #'denominator a))))

```

More golfed:

```
(defun l(a)(eval`(/(lcm,@(mapcar'numerator a))(gcd,@(mapcar'denominator a))))

```
> 1 votes

---
Tags: code-golf, number, arithmetic, rational-numbers
---


title: Matching homologous groups

text:
# Question
Title: Matching homologous groups
Homologous series, any of numerous groups of chemical compounds in each of which the difference between successive members is a simple structural unit.

As an example, Alkane is a homologous group where the chemical compounds are in \\$C\_nH\_{2n+2}\\$ format. \\$CH\_4\\$ (Methane) is part of the Alkane group because \\$CH\_4 \to C\_{1}H\_{2\cdot 1+2}\\$ and there because there is \\$n=1\\$ carbon atom, so there should be \\$2n+2\\$ hydrogen atoms. And there is \\$2×1+2 = 4\\$ hydrogen atoms. So Methane or \\$CH\_4\\$ qualifies for the Alkane group.

In this challenge we will be matching against 6 homologous groups:

* **Alkane** : \\$C\_nH\_{2n+2}\\$
* **Alkene** : \\$C\_nH\_{2n}\\$
* **Alkyne** : \\$C\_nH\_{2n-2}\\$
* **Alcohol** : \\$C\_nH\_{2n+1}OH\\$
* **Aldehyde** : \\$C\_nH\_{2n+1}CHO\\$
* **Carboxylic Acid** : \\$C\_nH\_{2n+1}COOH\\$

Input format will be like `CH_4` \\$ \to CH\_4\\$, `CH_3CHO` \\$ \to CH\_3CHO \\$, meaning that you need to write the subscript using an underscore (`_`). Output should be the group the compound belongs to.

**Test Cases**

```
CH_4 -> Alkane
C_2H_4 -> Alkene
C_2H_2 -> Alkyne
CH_3OH -> Alcohol
CH_3CHO -> Aldehyde
CH_3COOH -> Carboxylic Acid

```

Standard loopholes apply, shortest code wins. Input is guaranteed to be in these 6 categories and valid. Output needs to be exactly capitalized as in question. \\$n\\$ can be less than 2 (if it is omitted assume it is 1). There will be no leading zeros in \\$n\\$.

# Answer
# Python 3, 134 bytes

*-3 bytes thanks to @tsh*

Note that it fails for `CH_2`. It is unclear whether such a test case is valid, but I will keep this solution for now.

```
lambda e:['Aldehyde','Alcohol','Carboxylic Acid',0][e[::-1].rfind('O')]or'Alk%sne'%'eay'[eval(e.translate({67:45,72:43,95:43})+'//2')]

```

Try it online!

### Python 3, 137 bytes

Works for all cases including `CH_2`.

```
lambda e:['Aldehyde','Alcohol','Carboxylic Acid',0][e[::-1].rfind('O')]or'Alk%sne'%'yae'[eval(e.translate({67:43,72:43,95:'~-'})+'//-2')]

```

Try it online!
> 6 votes

# Answer
# JavaScript (Node.js), 115 bytes

```
s=>[[x,y]=s.match(/\d+/g),'Aldehyde','Alcohol','Carboxylic Acid'][s.length-s.search`O`]||`Alk${'aey'[x-y/2+1|0]}ne`

```

Try it online!

Thanks A username, -3 bytes.
> 5 votes

# Answer
# JavaScript (ES6), 122 bytes

I tried to gather all information within a single `.map()` statement, but this is not as competitive as I thought it would be.

```
s=>[`Alcohol`,`Alk${"aey"[s.split(/(\D_?)/).map(n=>++k*n?d=p-(p=n)/2:0,k=p=1)|-~d]}ne`,`Aldehyde`,,`Carboxylic Acid`][k%5]

```

Try it online!

### How?

We split the input with:

```
s.split(/(\D_?)/)

```

Each entry in the resulting array is:

* a letter followed by an optional `_` if its position is odd
* either an empty string or a number of its position is even

We walk through all entries and compute:

* \\$d\\$ : the difference between the penultimate number and the last one divided by \\$2\\$, assuming that there's an additional \\$1\\$ at the beginning (in case it's omitted like in `CH_4`)
* \\$k\\$ : the length of the array \\$+1\\$

We use \\$k\bmod5\\$ to figure out the main type of the homologous group:

```
 type     |  k | mod 5 | example
----------+----+-------+--------------------------------------------------------------
 Alk*ne   |  6 |   1   | C_2H_4   -> ['','C_','2','H_','4']
 Alcohol  | 10 |   0   | CH_3OH   -> ['','C','','H_','3','O','','H','']
 Aldehyde | 12 |   2   | CH_3CHO  -> ['','C','','H_','3','C','','H','','O','']
 Acid     | 14 |   4   | CH_3COOH -> ['','C','','H_','3','C','','O','','O','','H','']

```

We use the sign of \\$d\\$ to distinguish between Alkane, Alkene and Alkyne.
> 1 votes

# Answer
# Retina 0.8.2, 110 bytes

```
.*O..
Carboxylic Acid
.*O.
Alcohol
.*O
Aldehyde
_\d+
$*
CH.*|C(1+)H11\1\1
Alkane
C(1+)H\1\1
Alkene
C1.*
Alkyne

```

Try it online! Link includes test cases. Explanation:

```
.*O..
Carboxylic Acid
.*O.
Alcohol
.*O
Aldehyde

```

Identify these three groups by the position of the `O` from the end.

```
_\d+
$*

```

Convert the suffixes to unary.

```
CH.*|C(1+)H11\1\1
Alkane
C(1+)H\1\1
Alkene
C1.*
Alkyne

```

Identify these three groups by comparing the number of carbon and hydrogen atoms.
> 1 votes

# Answer
# C (gcc), ~~190~~ ~~188~~ 186 bytes

Thanks to ceilingcat for the -2.

The string is passed through a state machine that stores the initial C and O values and terminates early if there are no trailing characters after the second value. If the state ends early, then the difference between the two values is used to determine which type the molecule is; otherwise the first two trailing characters are used.

**Annotated version**

```
b,t, // State, molecule type
m[2], // C and O amounts
*a[]={"Aldehyde","Carboxylic Acid","Alcohol"};
f(char*s){
  for(b=3;*s++&&b--;) // Final states: 1 (alk[aey]ne), -1 (other)
    t=b? // Initial C and O
      m[b-1]=*s-95? // Is there an underscore (implies number)?
        1: // No, assume 1
        strtol(s+1,&s,0) // Yes, get number and go to next part
      : // Trailing characters (not alk[aey]ne)
        s[-1]-67? // First character is 'C'?
          2: // No, is alcohol
          *s==79; // Yes, either aldehyde or acid
  printf(~b?"Alk%cne":a[t],"y e a"[*m-m[1]*2+2]);
}

```

```
b,t,m[2],*a[]={"Aldehyde","Carboxylic Acid","Alcohol"};f(char*s){for(b=3;*s++&&b--;)t=b?m[b-1]=*s-95?1:strtol(s+1,&s,0):s[-1]-67?2:*s==79;printf(~b?"Alk%cne":a[t],"y e a"[*m-m[1]*2+2]);}

```

Try it online!
> 1 votes

---
Tags: code-golf, string, classification, chemistry
---


title: Cooperative Counting

text:
# Question
Title: Cooperative Counting
## Final results

# 1st place goes to *Follow*!

Honourable mentions to **The diff predictor** (2nd), and **Simple Killer**, **Low Blow** and **High to Low** (joint 3rd).

Other winners:

### (score competition) 1st - Simple Killer

Honourable mentions: **The diff predictor** and **Naiive**.

### (wins competition) 1st - Crab

Honourable mentions: **Follow** and **High to Low**.

Full results:

```
By score:
1: Simple Killer with 1208099 points
2: The diff predictor with 1053087 points
3: Naiive with 1051505 points
4: Follow with 905731 points
5: The dedicated counter with 769680 points
6: The Desperate Fighter with 769663 points
7: Low Blow with 763357 points
8: High to Low with 734011 points
9: Naughty or Nice? with 714912 points
10: Grim Trigger with 713702 points
11: Tit for tat with 713067 points
12: The primitive looker with 621028 points
13: Hard-coded with 428934 points
14: Zoidberg with 395702 points
15: FunnyNumber with 335179 points
16: Random with 329023 points
17: Shortcut with 257190 points
18: Meandian with 223051 points
19: Hawk with 47608 points
20: Crab with 14852 points

By wins:
1: Crab with avg. 19.0/19 wins
2: Follow with avg. 17.1/19 wins
3: High to Low with avg. 15.8/19 wins
4: Low Blow with avg. 14.9/19 wins
5: The diff predictor with avg. 14.1/19 wins
6: Meandian with avg. 13.7/19 wins
7: Hawk with avg. 13.0/19 wins
8: Hard-coded with avg. 11.7/19 wins
9: Naughty or Nice? with avg. 11.0/19 wins
10: Simple Killer with avg. 10.4/19 wins
11: The primitive looker with avg. 8.0/19 wins
12: Naiive with avg. 6.6/19 wins
13: Zoidberg with avg. 6.3/19 wins
14: Shortcut with avg. 5.0/19 wins
14: Grim Trigger with avg. 5.0/19 wins
16: FunnyNumber with avg. 4.0/19 wins
17: Random with avg. 3.0/19 wins
18: Tit for tat with avg. 1.0/19 wins
19: The dedicated counter with avg. 0.0/19 wins
19: The Desperate Fighter with avg. 0.0/19 wins

Combined leaderboard (fewer pts = better):
1: Follow  (6 pts)
2: The diff predictor  (7 pts)
3: Simple Killer  (11 pts)
3: Low Blow  (11 pts)
3: High to Low  (11 pts)
6: Naiive  (15 pts)
7: Naughty or Nice?  (18 pts)
8: Hard-coded  (21 pts)
8: Crab  (21 pts)
10: The primitive looker  (23 pts)
11: The dedicated counter  (24 pts)
11: Grim Trigger  (24 pts)
11: Meandian  (24 pts)
14: The Desperate Fighter  (25 pts)
15: Hawk  (26 pts)
16: Zoidberg  (27 pts)
17: Tit for tat  (29 pts)
18: FunnyNumber  (31 pts)
18: Shortcut  (31 pts)
20: Random  (33 pts)

```

---

# Cooperative Counting - Python 3 KOTH

Have you ever tried to count to 100 in an online forum or comment thread? It normally goes something like:

```
1
>2
>>3
>>>4
>>>>69 xD xD

```

the point being that someone will always try to ruin the fun.

# The game

This is a bit like the counting example above, except to make sure that neither player has an advantage from going first, each player will count at the same time as the other.

Your bot will be pitted against another bot. Your goal? Cooperatively count to 100.

Each round, your bot decides how far it is willing to cooperatively count with its opponent.

## Possible outcomes

**One player stops counting before the other**

The player who stopped counting first is awarded twice as many points as the value they counted up to. The other player gains no points.

**Both you and your opponent stop counting at the same time**

Neither of you gain any points.

**Both you and your opponent count all the way to 100**

Each player gains 100 points.

## Example

* Player 1: decides to count to 80
* Player 2: decides to count to 30

Player 2 gets 60 points, player 1 gets 0 points.

---

In another round:

* Player 1: decides to count to 57
* Player 2: decides to count to 57

Neither player gets points.

---

In yet another round:

* Player 1: decides to count to 100
* Player 2: decides to count to 100

Each player gets 100 points.

# Overall game flow

Your bot will be matched against other bots. It will play some number of rounds in a row, `n`, against the same bot. `n` will be somewhere in the range of 100 - 1000. This allows your bot to adapt to the other bot's strategy.

# Winning the KOTH

Each bot will have a go against each other bot. Your bot can win in three categories:

* **Score:** the total scores will be summed and the bot with the most points at the end will win.
* **Wins:** a 'win' is counted for the bot with the highest score after the `n` rounds have been played.
* **Overall:** both the other categories combined

# Technical details

Write a function in Python 3 with this signature:

```
def strategy(last_results: list[tuple[int, bool]]) -> int

```
* `strategy` is called once at the beginning of each round.
    + `last_results` is a list of previous results against the same opponent. Each item in the list is the result of a round in the form `(value reached, won)`, where `won` denotes whether the player won or not. If the player won through cooperation, this will be `True`.
    + e.g.: if you lose your first round because your opponent stops counting at 79, `last_results` looks like `[(79, False)]` at the start of round 2. If you then win round 2 by stopping counting at 34, `last_results` will look like `[(79, False), (34, True)]` at the start of round 3.
    + `strategy` should return the value at which the bot will stop counting. `1` stops counting immediately, `100` is an agreement to count cooperatively with the other bot all the way to the end, and e.g. `47` will stop counting when the value is `47`, earning the bot 84 points.

## Example bot

'Naiive' counts up to one before the number that was reached last round if it lost, otherwise it counts up to and including the number it won on.

```
def strategy(last_games):
    if len(last_games) == 0:
        return 100

    # Count up to one before the last number that was counted if we lost,
    # otherwise just up to the last number that was counted.
    if last_games[-1][1]:
        return last_games[-1][0]
    else:
        return max(1, last_games[-1][0] - 1)

```

## Legacy format (don't use)

**I've decided on a simpler format since the last one was causing confusion. Here is the old one for reference purposes. New submissions should be in the new format. Submissions using the legacy format do not need to update their submission.**

```
# Don't use this, see above
def strategy(last_results: list[tuple[int, bool]]) -> tuple:
    pass

def turn(current_value: int, *args) -> bool:
    pass

```

# Rules

* No cheating by interfering directly with your opponent (through global variables etc.).
* Your function should be relatively quick to execute - the quicker it is, the better.
* You *may* submit multiple entries.
* Submissions close a week from the start of this post, at 2021-04-17 11:00 UTC

# Controller, sandbox, arena

**The controller is available at https://github.com/jthistle/KOTH-counting.**

A couple of example bots are provided along with it to demonstrate how to use it.

`sandbox.py` provides a place to try out your bot against others and debug it.

`arena.py` is what I'll be using to calculate final scores. It pits each bot against each other bot.

# Answer
# Follow

```
def strategy(last_results):
    n = len(last_results)
    if n == 0: return 100
    if all(i == (1,False) for i in last_results): return 2 # nice to the crab
    a,b = last_results[-1]
    if n == 1:
        if b: return 100
        return 1+int(.97*(a-1))
    c,d = last_results[-2]
    if n >= 99 and a == 100: return 99
    if b and d: # won previous two rounds
        if (a+1,False) not in last_results:
            return min(100,a+1)
        return a
    else:
        a,c = sorted((a,c))
        return max(1,a*a//c-1)

```

Starts out by counting to 100. After round 99, if it previously counted to 100, it will only count to 99 (the reasoning is that it would otherwise tie with everything else that keeps counting to 100). If it detects the crab, it's nice (because it doesn't matter anyways). If it lost the previous round, then it counts lower than whatever won in the previous round (between 1 to 3 less). If it won the previous round, then it counts one further if it hasn't lost by counting that far before.

Edit: Made it use the ratio between the previous two moves to decide what to count to, made it only start increasing if it won the previous two rounds, and figured out a better way to check for the crab
> 8 votes

# Answer
# Crab

```
def strategy(last_results):
    return 1

```

Crab *always* stops counting, because it'd rather not get points than have the other bot beat it. It is because of Crab that we can't have nice things.
> 17 votes

# Answer
# Low Blow

```
import random
import statistics

def strategy(last_results):
        scores = list(map(lambda a: a[0], last_results))
        if not scores: return 99

        if len(scores) > 420 and scores[:3] == [69, 68, 68]:
                return 67

        decrements = [50, 69, 48]

        if all(score == 1 for score in scores): return 1

        for decrement in decrements:
                mold = [decrement]
                for _ in scores[1:]: mold.append(decrement - 1)
                if scores == mold:
                        return decrement - 1

        if scores[0] == 65:
                if scores[-1] == 1: return 1
                return random.randint(1, 48)

        if scores == [98]:
                return 97

        if len(scores) == 1 and scores[0] < 48:
                return scores[0]

        if last_results[:2] == [(99, True), (99, False)]:
                return max(scores[-1] - 1, 1)

        if scores[:2] == [47, 31]    : return max(min(50, int(sum(scores) / (len(scores) * 1.5))) - 1, 1)
        if scores[:2] == [99, 97]    : return max(scores[-1] - 3, 1)
        if scores[:2] == [99, 98]    : return max(scores[-1] - 2, 1)
        if scores[:3] == [99, 99, 98]: return max(scores[-1] - 1, 1)

        if scores[:2] == [98, 97]    :
                htl_losses = [result[0] for result in last_results if result[1]]
                return max(min(htl_losses) - len(htl_losses) - 2, 1)

        if len(scores) > 1 and scores[0] == scores[1] != 99:
                mean = round(statistics.mean(scores))
                median = round(statistics.median(sorted(scores)))

                if mean == median:
                        return max(mean - 1, 1)
                return max(abs(median - mean) - 1, 1)

        if scores[-1] == 1:
                return 1

        if len(scores) <= 3: return 99

        deltas = [scores[~0] - scores[~1], scores[~1] - scores[~2]]
        if any(deltas): return random.randint(37, 50)

        return 99

```

Low Blow's strategy is somewhat "kamikaze". It aims to reduce the opposition bot's score as much as possible, even if that means that Low Blow scores fewer points. However, it does aim to capitalise on points against specific bots where possible.

It does this by identifying the bot it's against, then playing their own strategy against them, but one lower than what they'd return. Either, the values are constant and Low Blow collects a bunch of points, or the values eventually reach 1, at which point Low Blow will likely\\${}^\*\\$ have more points and neither bot will get more

\\${}^\*\\$"Likely" because of randomness from Hard-coded
> 12 votes

# Answer
# The dedicated counter

Updated to use the new format (slight performance gain, which adds up):

```
def strategy(last_results):
    return 100

```

Original:

```
def strategy(last_results):
    return ()

def turn(current_value, *args):
    return True

```

No matter what the opponent does, this bot will always count up. With determination it keeps going in the face of potential trolls. I'll be writing a more thought out bot once I can see the examples.
> 8 votes

# Answer
# Simple Killer

```
def strategy(last_results):
    if not len(last_results):
        return 100
    if len(last_results) == 999 and last_results[-1][0] == 100:
        return 99
    last_move = last_results[-1]
    if last_move in last_results[:-1]:
        pos = last_results.index(last_move)
        if last_results[pos + 1][1]:
            return last_results[pos + 1][0]
        return max(last_results[pos + 1][0] - 1, 1)
    return 100

```

Simple Killer targets a certain class of bot: those who consider only the most recent move (or don't look at the past). By determining exactly how the opposing bot typically reacts, Simple Killer is able to slowly figure out the optimal move in any given circumstance.

It either loses by a narrow margin, wins by a huge margin, or plays nice (if the other bot is happy to just sit at 100).
> 8 votes

# Answer
# The primitive looker

This is a bot which learns from its previous rounds.

New version:

```
def strategy(last_results):
    if not last_results:
        return 100
    if any(not x[1] for x in last_results):
        if last_results[-1][0] - 2 > 0:
            return last_results[-1][0] - 2
        return 100
    return 99

```

Legacy version:

```
import random

def strategy(last_results):
    try:
        return (last_results, )
    except:
        return ([], )

def turn(current_value, res):
    v = 99
    m = 2
    g = True
    for i in res:
        if not i[1]:
            g = False
            break

    if res == []:
        c = True
    else:
        if res[-1][1] and g:
            if current_value == v:
                c = False
            else:
                c = True
        else:
            if current_value == res[-1][0] - m:
                c = False
            else:
                c = True

    return c

```

Lucky this is not ...
Try it online!
> 6 votes

# Answer
# Shortcut

Updated to use the new format (slight performance gain, which adds up):

```
def strategy(last_results):
    return 50

```

Original:

```
def strategy(last_results):
    return ()

def turn(current_value, *args):
    return current_value != 50

```

Not the patient type. Takes the reward of 100 on turn 50, instead of being a team player and getting taken advantage of down the line. Shortcut has some trust issues.

I'll start on a more complicated bot soon.
> 5 votes

# Answer
# FunnyNumber

```
def strategy(last_results):
	if len(last_results) > 420:
		return last_results[420][0]
	return 69

```

Try it online!

Like the joke itself, this bot is very uncreative. If there has been more than 420 rounds, FunnyNumber returns the result of the 420th (0-indexed) round. Otherwise, it counts up to 69 to try to earn 138 points.

Interestingly, this isn't the worse bot. Running a couple of arenas locally with this as a contestant, FunnyNumber gets 3/6 wins
> 4 votes

# Answer
# Zoidberg

```
def strategy(_):
        return 48

```

Zoidberg is like a crab, but different. Credit to user for the original idea.

I brute forced what number provides an optimal score with this approach. Surprisingly, this is better overall than Crab. Running locally I get

| Bot | Score | Wins | Overall |
| --- | --- | --- | --- |
| Crab | 12th | 1st | 6th |
| Zoidberg | 5th | 5th | 5th |
> 4 votes

# Answer
# High to Low

```
def strategy(last_results):
    if last_results:
        losses = [r[0] for r in last_results if not r[1]]
        if losses:
            return max(1, min(losses)-len(losses))
        num_of_rounds = len(last_results)
        if num_of_rounds>15 and len(losses)/num_of_rounds>0.6:
            return 1
    return 98

```

This bot always counts to `98` unless it has lost a round. Once this bot loses a round, it only counts to numbers lower than its lowest loss. If it has lost more than `60%` of the rounds, it plays `1`.

**Edit:** Changed the algorithm for calculating the number the bot should count to after losing from `max(1, min(losses)-1-len(losses))` to `max(1, min(losses)-len(losses))`. Hopefully, this should allow the bot to capitalize on static bots because it now counts to `1` below and not `2` below.
> 4 votes

# Answer
# Copycat

```
import urllib.request
import bs4 as bs
import random
contents = urllib.request.urlopen("https://codegolf.stackexchange.com/questions/223202/cooperative-counting").read()
html = bs.BeautifulSoup(contents, 'html.parser')

answers = html.findAll('div', {"class": "answer"})

strategies = []
for answer in answers:
    code = answer.find('div', {"class": "answercell"}).findAll('code')
    for any in code:
        strategies.append(str(any.contents[0]))

def newStrat(badOne = None):
    if not badOne == None: strategies.remove(badOne)
    return random.choice(strategies)
pick = newStrat()

def strategy(games):
    global pick
    try:
        exec(pick.replace('strategy','strategycopy'),globals())
        return strategycopy(games)
    except:
        pick = newStrat(pick)
        return strategy(games)

```

I didn't really feel like making a strategy up, so this bot will just copy someone elses answer.
> 3 votes

# Answer
# Meandian

```
import random
import statistics as stats
def strategy(last_results):
    def clamp(minimum, x, maximum):
        return max(minimum, min(x, maximum))
    last_results = sorted(map(lambda a: a[0], filter(lambda a: not a[1], last_results)))
    if not len(last_results):
        return random.randint(1,47)
    else:
        mean = round(stats.mean(last_results))
        median = round(stats.median(last_results))
    if mean == median:
        return mean
    elif mean > median:
        return clamp(1, median - random.randint(1,mean - median), 100)
    else:
        return clamp(1, mean - random.randint(1,median - mean), 100)

```

This bot calculates the mean and median, and uses those calculations to predict a range of values that will be less than the other bot's choice, and will randomly choose one of them. It is also designed to be difficult to hardcode a solution to beat it but still handle other bots robustly.

edit: Meandian now only considers the round where the other bot wins during calculations to prevent itself from driving down itself unnessecarily.
> 3 votes

# Answer
## Tit for tat

```
def strategy(last_results):
    return last_results[-1][0] if last_results else 100

```

Very basic strategy.
> 3 votes

# Answer
# The diff predictor

```
def strategy(last_results):
    previous_values = list()
    diffs = list()
    for num,result in last_results:
        if result:
            oppo_play = min(100,num+1)
        else:
            oppo_play = num
        if len(previous_values)>0:
            diffs.append(oppo_play-previous_values[-1])
        previous_values.append(oppo_play)

    if len(previous_values) == 0:
        move = 100
    elif len(previous_values) == 1:
        move = previous_values[0]
    else:
        diffs = diffs[-10:]
        if len(diffs)>2:
            # remove outliers
            diffs.remove(min(diffs))
            diffs.remove(max(diffs))
        meandiff = sum(diffs)/len(diffs)
        move = previous_values[-1] + meandiff -1

    if move==99 and len(last_results)<950:
        # Let's be nice (for a while)
        move=100
    return min(100, max(1, round(move)))

```

Predicts what the opponent will play next based on the average difference between consecutive previous plays (discarding highest and lowest, to avoid being fooled by FunnyNumber). Assumes the opponent played N+1 whenever it wins with N.

It plays 100 as long as the opponent does the same, until towards the last games, where it decides there's no use in being nice anymore.
> 3 votes

# Answer
# Lumberjack

The plan is get to a winning position and then head towards 1 faster than the opponent can recover. Partly inspired by other bots here!

```
def strategy(last_results):
    round_number = len(last_results)
    if round_number == 0:
        return 100
    if all(i == (1, False) for i in last_results):
        return 1  # lumberjacks don't like crabs
    score, success = last_results[-1]
    if round_number == 1:
        if success and score == 100:
            return 100
        return max(1, score/2)
    old_score, old_success = last_results[-2]
    if success and old_success:  # won previous two rounds
        if score == 100:
            return 97  # try and get in under fair bots
        else:
            # minimal pruning, light regrowth
            return max(1, (score+old_score)*0.4 + 15)
    if not success:
        if not old_success:
            # heavy pruning
            return max(1, score*0.5)
            # light pruning
        return max(1, score*0.75)
    else:
        # regrow by small amounts
        return min(100, score + old_score*0.2 + 10)

```

I dreamt this up on Thursday, but I wasn't able to write it down and experiment until today. It's a late entry so I'm not expecting any prizes.
> 3 votes

# Answer
# The Desperate Fighter

# Python 3, 285 bytes

```
def strategy(last_results):
    if len(last_results) == 0:
      return True,
    pos = last_results[-1][0]
    if pos in [49,50]:
      return False,
    if pos in list(range(10,21)):
      return False,
    else:
      return True,

def turn(current_value, *args):
    return args[0]

```

Try it online!

This bot will try to win in anyways it can....

# Bot handling

* Lyxal: I stop at 50 to attack his bot
* math: I stop at 10 to 20 for defence to his bot
* Redwolf: I stop at 49 to attack his bot
> 2 votes

# Answer
# Naughty or Nice?

```
def strategy(last_results):
        scores = list(map(lambda a: a[0], last_results))

        if all(score == 100 for score in scores):
                if len(scores) == 999:
                        return 98
                return 100

        constant_bots = {
                69: 68,
                68: 67,
                50: 49,
                48: 47
        }

        return constant_bots.get(scores[-1], 1)

```

Naughty or Nice? works on a very simple premise: Every match, one bot must be Naughty.

* If the opponent counts to 100, Naughty or Nice? considers it "nice", and so Naughty or Nice? must be Naughty. It counts up to 100 with its opponent until it reaches the final round, where it stops at 98
* Otherwise, the other bot is Naughty, and so doesn't deserve any points. In this case, either:
    + The opponent is a "constant" bot (FunnyNumber, Zoidberg, Shortcut), so we return 1 less than them
    + The opponent is not a constant bot, so we throw a tantrum and play 1 for the rest of the match
> 2 votes

# Answer
# Hard-coded

```
import random
def strategy(last_results):
  if len(last_results) == 0:
    return 65
  if last_results[-1][0] in [50,49]:
    return 49 # Shortcut detected, attack!
  if last_results[-1][0] in [69,65]:
    return 65 # FunnyNumber detected, attack!
  if last_results[-1][0]==1:
    return 1 # Crab detected, defend!
  else:
    return random.randint(1,100) # give away, my mind is boggling with numbers

```

It is mainly designed to compete against caird and Redwolf and user
> 1 votes

# Answer
# Hawk

A quick internet search reveals hawks eat pythons \>:).

This strategy takes the average, weighted a bit, of the winning scores and returns its floor, or 47 at the beginning. Purely functional and not python \>:).

---

A Pure Python version (untested), courtesy of caird coinheringaahing:

```
def strategy(last_results):
  if not last_results:
    return 47
  return max(1, min(50, sum(map(lambda t: t[0], last_results)) // (len(last_results)*1.5)))

```

---

## In Hy

```
(defn strategy [last-results]
  (if last-results
    (max 1 (min 50
      (// (reduce +
           (map (fn[t] (get t 0)) last-results))
         (* 1.5 (len last-results)))))
    47))

```
> 1 votes

# Answer
# Grim Trigger

```
def strategy(last_results):
    if any([not r[1] for r in last_results]):
        return 1
    else:
        return 100

```

This bot prefers to cooperate and count to `100`, but if the opponent tries to troll it, it pulls the trigger and only counts to `1` for the rest of the round.
> 1 votes

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


title: Shrinking Triangles

text:
# Question
Title: Shrinking Triangles
Write an infinite list of triangle codes, defined as code where the i-th line has i bytes for all lines, such that the i-th code generates (i-1)th code and has 1 more line than the (i-1)th code.

The score is the number of lines in the initial code. Lowest score wins.

For example, if

```
.
..
...
....

```

is outputted by

```
.
..
...
....
print

```

which is outputted by

```
.
..
...
....
print
print.

```

and so on, then the score is 4.

Sandbox

# Answer
# JavaScript (ES6), Score  ~~10~~  9

Below is an example starting point with 15 lines. Bigger triangles are obtained by padding the end with 0's while preserving the final ``)`.

```
0
f=
_=>
  `0
${`f=
`+f}`.
/*###*/
replace(
/..\n.+$/
,'`)'||`00
00000000000
000000000000
0000000000000
00000000000000
0000000000000`)

```

which is eventually reduced to:

```
0
f=
_=>
  `0
${`f=
`+f}`.
/*###*/
replace(
/..\n.+`)

```

Try it online!
> 9 votes

# Answer
# , 278 lines

The output of this 279-byte program:

```
'->w;s=substring;`+`=paste0;x=nchar(w);y=s(w,1,138);z=sQuote(s(w,1,x-1))+y;for(i in 2:nchar(z)-2)cat("#"+s(z,1,i),sep=intToUtf8(10));cat(z).'->w;s=substring;`+`=paste0;x=nchar(w);y=s(w,1,138);z=sQuote(s(w,1,x-1))+y;for(i in 2:nchar(z)-2)cat("#"+s(z,1,i),sep=intToUtf8(10));cat(z)

```

Try it online!

Each successive program is created by adding an additional character character (any character) at position 139 of the final line of the 'base' program.

**Ungolfed program generator:**

```
w='->w;s=substring;`+`=paste0;x=nchar(w);y=s(w,1,138);z=sQuote(s(w,1,x-1))+y;for(i in 2:nchar(z)-2)cat("#"+s(z,1,i),sep=intToUtf8(10));cat(z).'
                                # define string w as the golfed working program code,
                                # appended with extra characters to generate
                                # successively longer versions;
`+`=paste0                      # redefine `+` to concatenate strings;
x=nchar(w)                      # Now, get x = the number of characters of w
y=substring(w,1,138)            # define y as the working program code without any extra characters
z=sQuote(substring(w,1,x-1))+y  # define z as the previous full working program: that is,
                                # the definition of w minus 1 character, plus the program code.
for(i in 2:nchar(z)-2){         # Loop up to the length of z minus 1
  cat("#"+s(z,1,i),sep="\n")    # printing its prefixes after a "#"
}                               # (so these are all comments in the outputted program),
cat(z)                          # finally output the previous program code.

```
> 6 votes

# Answer
# Zsh, score 5

The pattern repeats like this:

```
#
h\
ea\
d -\
n-1 \
$0 ###
#######
########
#########
##########
###########
############
#############
# ad infinitum

```

Try it online!

With this as the ultimate program:

```
#
h\
ea\
d -\
n-1 \
$0 ###

```
* `#`: comments, ignored
* `h\ea\d -\n-1 \$0`: the backslashes and line breaks are eaten up to produce `head -n-1 $0`
    + `head`: print the first \\$ n \\$ lines
    + `$0`: of the current program
    + `-n-1`: with \\$ n = -1 \\$, which is treated as "all but the last"
> 6 votes

# Answer
# Haskell (GHC 8.4.1, `-cpp`), score 28

This is the initial triangle (the first line is actually a space).

```

q\
=p\
rint
p=pu\
tStr;\
f(x:y)\
|length\
 y>25=p"\
f ">>q('.\
'<$y);f s=\
p$show s++"\
]\n";l=putSt\
rLn;main=   do
l. concat<>map\
M_((>>p",\\\10"\
).p.show)$init[ \
" \nq\\\n=p\\\n",\
"rint\np=pu\\\nt",\
"Str;\\\nf(x:y)\\",\
"\n|length\\\n y>2",\
"5=p\"\\\nf \">>q('",\
".\\\n'<$y);f s=\\\n",\
"q$show s++\"\\\n]\\n",\
"\";l=putSt\\\nrLn;mai",\
"n=   do\nl. concat<>ma",\
"p\\\nM_((>>p\",\\\\\\10",\
"\"\\\n).p.show)$init[ \\",\

```

To obtain the the 29-lines triangle we add the following line.

```
".........................."]

```

From the 30th line onwards, the pattern becomes regular.

```

q\
=p\
rint
p=pu\
tStr;\
f(x:y)\
|length\
 y>25=p"\
f ">>q('.\
'<$y);f s=\
p$show s++"\
]\n";l=putSt\
rLn;main=   do
l. concat<>map\
M_((>>p",\\\10"\
).p.show)$init[ \
" \nq\\\n=p\\\n",\
"rint\np=pu\\\nt",\
"Str;\\\nf(x:y)\\",\
"\n|length\\\n y>2",\
"5=p\"\\\nf \">>q('",\
".\\\n'<$y);f s=\\\n",\
"q$show s++\"\\\n]\\n",\
"\";l=putSt\\\nrLn;mai",\
"n=   do\nl. concat<>ma",\
"p\\\nM_((>>p\",\\\\\\10",\
"\"\\\n).p.show)$init[ \\",\
".........................."]
f ".........................."
f "..........................."
f "............................"

```

Try it online!

You can find a program to generate arbitrarily large triangles here.

## How?

We use the `-cpp` flag to allow line breaking in the source code by means of `\`. GHC 8.4.1 is necessary since it is the first version to export the `(<>)` `Semigroup` operator in `Prelude`. My answer uses a variation of this clever technique typically employed in quines. Here is the de-triangularized code.

```
q=print
p=putStr
f(x:y)|length y>25=p"f ">>q('.'<$y)
f s=p$show s++"]\n"
l=putStrLn
main=do
    l.concat<>mapM_((>>p",\\\10").p.show)$init[
        " \nq\\\n=p\\\n",
        "rint\np=pu\\\nt",
        "Str;\\\nf(x:y)\\",
        "\n|length\\\n y>2",
        "5=p\"\\\nf \">>q('",
        ".\\\n'<$y);f s=\\\n",
        "q$show s++\"\\\n]\\n",
        "\";l=putSt\\\nrLn;mai",
        "n=   do\nl. concat<>ma",
        "p\\\nM_((>>p\",\\\\\\10",
        "\"\\\n).p.show)$init[ \\",
        ".........................."]
    f ".........................."
    f "..........................."
    f "............................"
    f "............................."

```

The part before `f ".........................."` defines a function `f` and then prints itself (minus the last line `".........................."]`). The behaviour of `f` depends on the length of its argument: if the length is `26` then it prints `".........................."]`, otherwise if prints `f "....[...]....."`, where the number of dots is one less then the length of its argument. In both cases, `f` is basically printing the line just before its invocation.

By the way, making sure that the strings of the list had the correct length was a total nightmare. You think adding some random spaces to the code above would be enough? No no no! I spent way too much time trying all the possible combinations of `putStr` and `putStrLn`, moving things around to change the number of `\` in the code. The winning move was finally replacing a `\n` with `\10`, and after that everything was magically aligned.
> 4 votes

---
Tags: code-golf, source-layout, code-generation
---


title: How many bystanders will help?

text:
# Question
Title: How many bystanders will help?
## Flavortext

The Bystander Effect is a phenomenon where individuals are less likely to help a victim if other people are present. The idea is that as there are more people around, the individual burden is less, and each individual thinks "someone else will help them", which results in the counterintuitive fact that fewer people will help when there are more people.

(This is why if you're in public and something bad happens and you / someone else needs help, you should address random individuals ("you in the red shirt") to help specifically rather than "someone please help" to bypass this psychological phenomenon)

Let's take a very simplified interpretation of this theory and assume everyone has a numerical threshold for helping.

## Specification

A list of people will be given, each with a threshold to help. The threat level is 1. A person will help if and only if the threat level divided by the number of people in the crowd is greater than equal to their threshold. When a person decides to help, they leave the crowd. This means that the individual threat, which is the threat level (1) divided by the size of the crowd, is now higher as a result because the crowd is smaller.

The total threat level (1) never changes, for simplicity.

How many people end up helping?

## Input

You are given a list of floating point numbers in any reasonable format. This list will be non-empty, and every number will be in the inclusive range from 0 to 1. You may assume the list is sorted in either order you would like.

## Output

You are to output a single integer, indicating how many of the individuals decide to help.

## Example

Consider the test case `0.2, 0.2, 0.3, 0.6, 0.8`. The crowd has five people, so the threat to each individual is 0.2. Therefore, the first two people will help. Now, the crowd is `0.3, 0.6, 0.8`. Since there are only three people, the threat to each individual is now 0.3. Therefore, the third person will now decide to help. The crowd is now `0.6, 0.8`, so the individual threat is 0.5, and nobody decides to help anymore. Therefore, the final result is `3`.

## Test Cases

```
1                        -> 1
0.5, 0.8                 -> 2 # 0.8 initially won't help, but will when 0.5 leaves
0.2, 0.2                 -> 2 # both will help initially
0.2, 0.2, 0.3, 0.6, 0.8  -> 3 # 0.2 and 0.2 leaving prompts 0.3 to help, but the other two won't help
0, 0.25, 0.33, 0.5, 1    -> 5 # all of them help only after the previous person left, starting with 0
0, 0.25, 0.34, 0.34, 1   -> 2 # 0 and 0.25 help, but 0.34 is just a bit too indifferent to help, which means 1 will never help either
0.5, 0.5, 0.5            -> 0 # nobody helps. RIP

```

## Reference Implementation

This implementation (Python) shows the final answer at the very end. It also breaks down the process stage-by-stage.

# Answer
# Jelly,  ~~9 8~~  7 bytes

(Saved 1 when the assumption of sorted input was allowed, and another realising there was no need to floor the inverses.)

```
İ<Jṣ1ṪL

```

A monadic Link accepting a list of floating-point numbers in \\$\[0,1\]\\$ sorted in descending order that yields an integer.

**Try it online!** Or see the test-suite.

### How?

Effectively this evaluates how many people need to be in the crowd to stop each person helping, identifies crowd sizes that would be too big for anyone to help if those most likely to help have been removed, then counts those in excess of the biggest of those crowd sizes.

```
İ<Jṣ1ṪL - Link: list of thresholds, T  e.g. [1, 0.34, .34, .25, 0]
İ       - inverse (T)                       [1, 2.94, 2.94. 4, inf]
  J     - range of length (T)               [1, 2, 3, 4, 5]
 <      - less than?                        [0, 0, 1, 0, 0]
   ṣ1   - split at ones                     [[0, 0], [0, 0]]
     Ṫ  - tail                              [0, 0]
      L - length                            2

```

---

Equivalently:

```
İ<JṚÄċ0
   Ṛ    - reverse                           [0, 0, 1, 0, 0]
    Ä   - cumulative sums                   [0, 0, 1, 1, 1]
     ċ0 - count zeros                       2

```
> 13 votes

# Answer
# , 13 bytes

*-2 thanks to Jonah!*

```
-&#(#~%<#)^:_

```

Try it online!

```
-&#(#~%<#)^:_
   (     )^:_ until result does not change
      %<#     (1 % element) smaller than length of the list
    #~        filter out other elements
-&#           length(original list) - length(filtered out list)

```
> 9 votes

# Answer
# Jelly, 9 bytes

```
Lİ<SɗƬạLṪ

```

Try it online!

Does not assume sorted input. :/

Since shrinking the crowd never makes anyone not help, this calculates the new crowd size from the previous one until nobody new leaves.

```
     Ƭ       Loop until a fixed point, starting from
L            the length of the input:
  <Sɗ        how many elements of the input are strictly greater than
 İ           the reciprocal?
      ạL     Subtract each intermediate result from the length of the input,
        Ṫ    and return the last one.

```

Uses `Ƭ ... Ṫ` instead of `ÐL` because `ÐL` passes the previous left argument as the right argument rather than reuse the original right argument, given a dyad.
> 7 votes

# Answer
# Jelly, 7 bytes

```
×JỊẠÐƤS

```

Try it online!

Assumes the input is sorted descendingly (thanks to @caird). 8 bytes without that assumption:

### Jelly, 8 bytes

```
JU×ṢỊẠƤS

```

Try it online!

The idea here is that if we consider the sorted list, once anyone doesn't go, nobody after them will go either. Furthermore, considering an individual, they will only go if everyone *before* them went, so their individual condition for helping is `1/reversed_index > threshold`, i.e. `threshold * reversed_index < 1`.

Thus:

```
JU       ' [len(l)..1], i.e. reversed index
  ×Ṣ     ' times the sorted values
    Ị    ' <=1
     ẠƤ  ' map 'all' over prefices, results in 1s over the prefix of helpers
       S ' sum

```
> 7 votes

# Answer
# Charcoal, ~~16~~ 13 bytes

```
ＩＬ⊟⪪⭆Ａ›×ι⊕κ¹1

```

Try it online! Link is to verbose version of code. Requires input sorted in descending order. Edit: Saved 3 bytes after following @DominicvanEssen's advice. Explanation:

```
     Ａ          Input array
    ⭆           Map over elements and join
          κ     Current index
         ⊕      Incremented
       ×        Multiplied by
        ι       Current value
      ›         Is greater than
           ¹    Literal `1`
   ⪪            Split on
            1   Literal string `1`
  ⊟             Pop last element
 Ｌ              Length
Ｉ               Cast to string
                Implicitly print

```
> 7 votes

# Answer
# JavaScript (ES6), 39 bytes

Essentially the same answer as below but it assumes that the input is sorted from lowest to highest, which is now allowed.

```
a=>(n=a.length)-(a.map(k=>n-=k*n<=1),n)

```

Try it online!

---

# JavaScript (ES6), 46 bytes

```
a=>(n=a.sort().length)-(a.map(k=>n-=k*n<=1),n)

```

Try it online!

### Commented

```
a =>               // a[] = input
  ( n = a.sort()   // sort the input; although the sort is in lexicographical
                   // order, it's OK for floats in [0, 1]
        .length    // initialize n to the length of the array
  ) - (            //
    a.map(k =>     // for each value k in a[]:
      n -=         //   decrement n if:
        k * n <= 1 //     k * n is less than or equal to 1
    ),             // end of map()
    n              // subtract the new value of n from the original value
  )                //

```
> 5 votes

# Answer
# , ~~56~~ 44 bytes

*Edit: saved 12 bytes after looking at Jonathan Allan's answer: please upvote that!*

```
function(c,d=sum(c|1))match(T,1/c<d:1,d+1)-1

```

Try it online!
> 5 votes

# Answer
# Wolfram Language (Mathematica), 34 bytes

```
LengthWhile[#,l=Tr[1^#];1>=l--#&]&

```

Try it online!

Requires input to be sorted, least to greatest.

---

Iteratively, 35 bytes:

```
0//.x_:>Tr@UnitStep[x#-Tr[1^#]#+1]&

```

Try it online!

No sorting requirements.
> 5 votes

# Answer
# Haskell, 33 bytes

```
f(x:y)|sum(x<$x:y)<=1=1+f y
f _=0

```

Try it online!

The relevant function is `f`, which takes as input the list of tolerances in increasing order.

## How?

The only trick I think it's worth showcasing is the `sum(x<$x:y)` part. Its job is to compute `x*length(x:y)`, but:

1. it's 2 bytes shorter, and
2. since `x` is a `Double` and `length` returns an `Int`, Haskell would complain if we tried to multiply them together; to fix this issue, the monstrosity we would need is `x*toEnum(length$x:y)`, which is 9 bytes longer than `sum(x<$x:y)`.
> 5 votes

# Answer
# Jelly, 12 bytes

```
×Ị¥ÐḟL$ÐLLạL

```

Try it online!

```
×Ị¥ÐḟL$ƬẈ.ịI

```

Try it online!

```
×Ị¥ÐḟL$ƬẈạLṪ

```

Try it online!

Go upvote Jonathan Allan's or Unrelated String's answers, they're much better.

## How they work

```
×Ị¥ÐḟL$ÐLLạL - Main link. Takes a list L on the left
      $ÐL    - Repeat the previous 2 links until it reaches a fixed point:
     L       -   Yield the length of the list
  ¥Ðḟ        -   Remove elements which return false under the previous 2 links:
 Ị           -     They are less than or equal to 1 when
×            -     multiplied by the length
         L   - Get the length of the fixed point
           L - Get the length of L
          ạ  - Absolute difference

×Ị¥ÐḟL$ƬẈ.ịI - Main link. Takes a list L on the left
      $Ƭ     - Repeat the previous 2 links until it reaches a fixed point. Return all steps:
     L       -   Yield the length of the list
  ¥Ðḟ        -   Remove elements which return false under the previous 2 links:
 Ị           -     They are less than or equal to 1 when
×            -     multiplied by the length
        Ẉ    - Lengths of each step
         .ị  - Get the first and last
           I - Subtract them

×Ị¥ÐḟL$ƬẈạLṪ - Main link. Takes a list L on the left
      $Ƭ     - Repeat the previous 2 links until it reaches a fixed point. Return all steps:
     L       -   Yield the length of the list
  ¥Ðḟ        -   Remove elements which return false under the previous 2 links:
 Ị           -     They are less than or equal to 1 when
×            -     multiplied by the length
        Ẉ    - Lengths of each step
          L  - Length of L
         ạ   - Absolute differences
           Ṫ - Get the last one

```
> 4 votes

# Answer
# Python 2, <sup>~~72~~ \\$\cdots\\$ ~~43~~</sup> 42 bytes

Saved 7 bytes thanks to the man himself Arnauld!!!
Saved ~~3~~ 4 bytes thanks to dingledooper!!!

```
f=lambda l:l>[]>1>=len(l)*l.pop()and-~f(l)

```

Try it online!

Assumes the input is sorted from highest to lowest.
> 4 votes

# Answer
# Jelly, 13 bytes

```
>Lİ$x@ƊÐLL_@L

```

```
>Lİ$x@ƊÐLL_@L
>Lİ$          arg is greater than 1/len(arg)
    x@        filter (finds people left)
       ÐL     apply until converged
         L_@L length of argument minus length

```

Try it online!
> 3 votes

# Answer
# Pyth, 15 bytes

```
l-Qu.xf<c1lGTGY

```

Test suite

Explanation:

```
l-Qu.xf<c1lGTGY  | Full program
l-Qu.xf<c1lGTGYQ | with implicit variables
-----------------+------------------------------------------------------------------------------
      f      G   | filter the list G for elements T such that
        c1lG     | 1 / length of G
       <    T    | is less than T
    .x        Y  | unless an error is thrown in which case return the empty list
   u           Q | repeat the above until a previous result is repeated, starting with the input
l-Q              | length of input with the elements of the resulting list removed

```
> 3 votes

---
Tags: code-golf, math, array
---