# Question
Title: Center of Mass from a list of coordinates and their masses
Here is a quick Monday morning challenge...

Write a function or program in the least number of bytes that:

* Takes as input a list of `[x,y]` coordinates
* Takes as input a list of the `[x,y]` coordinates' respective masses
* Outputs the calculated center of mass in the form of `[xBar,yBar]`.

Note:

* Input can be taken in any form, as long as an array is used.

The center of mass can be calculated by the following formula:

In plain English...

* To find `xBar`, multiply each mass by its respective x coordinate, sum the resulting list, and divide it by the sum of all masses.
* To find `yBar`, multiply each mass by its respective y coordinate, sum the resulting list, and divide it by the sum of all masses.

Trivial Python 2.7 example:

```
def center(coord, mass):
    sumMass = float(reduce(lambda a, b: a+b, mass))
    momentX = reduce(lambda m, x: m+x, (a*b for a, b in zip(mass, zip(*coord)[0])))
    momentY = reduce(lambda m, y: m+y, (a*b for a, b in zip(mass, zip(*coord)[1])))
    xBar = momentX / sumMass
    yBar = momentY / sumMass
    return [xBar, yBar]

```

Test Cases:

```
> center([[0, 2], [3, 4], [0, 1], [1, 1]], [2, 6, 2, 10])
[1.4, 2.0]

> center([[3, 1], [0, 0], [1, 4]], [2, 4, 1])
[1.0, 0.8571428571428571]

```

This is code-golf, so the least number of bytes wins!

# Answer
# MATL, ~~6~~ 5 bytes

```
ys/Y*

```

Input format is a row vector with the masses, then a two-column matrix with the coordinates (in which spaces or commas are optional).

* First example:

```
[2, 6, 2, 10]
[0,2; 3,4; 0,1; 1,1]

```
* Second example:

```
[2, 4, 1]
[3,1; 0,0; 1,4]

```

**Try it online!**

### Explanation

Let `m` denote the vector of masses (first input) and `c` the matrix of coordinates (second input).

```
y     % implicitly take two inputs. Duplicate the first.
      % (Stack contains, bottom to top: m, c, m)
s     % sum of m.
      % (Stack: m, c, sum-of-m)
/     % divide.
      % (Stack: m, c-divided-by-sum-of-m)
Y*    % matrix multiplication.
      % (Stack: final result)
      % implicitly display

```
> 21 votes

# Answer
# Mathematica, 10 bytes

```
#.#2/Tr@#&

```

Example:

```
In[1]:= #.#2/Tr@#&[{2,6,2,10},{{0,2},{3,4},{0,1},{1,1}}]

Out[1]= {7/5, 2}

```
> 7 votes

# Answer
# Mathcad, 19 "bytes"

* Uses Mathcad's tables for data input
* Uses Mathcad's built-in vector scalar product for multiplying axis ordinate and mass
* Uses Mathcad's built-in summation operator for total mass

As Mathcad uses a 2D "whiteboard" and special operators (eg, summation operator, integral operator), and saves in an XML format, an actual worksheet may contain several hundred (or more) characters. For the purposes of Code Golf, I've taken a Mathcad "byte count" to be the number of characters or operators that the user must enter to create the worksheet.

The first (program) version of the challenge takes 19 "bytes" using this definition and the function version takes 41 "bytes".
> 7 votes

# Answer
## Jelly, 6 bytes

```
S÷@×"S

```

or

```
÷S$×"S

```

Input is via two command-line arguments, masses first, coordinates second.

Try it online!

### Explanation

```
S       Sum the masses.
   x"   Multiply each vector by the corresponding mass.
 ÷@     Divide the results by the sum of masses.
     S  Sum the vectors.

```

or

```
÷S$     Divide the masses by their sum.
   ×"   Multiply each vector by the corresponding normalised mass.
     S  Sum the vectors.

```
> 6 votes

# Answer
## Julia, ~~25~~ 17 bytes

```
f(c,m)=m*c/sum(m)

```

Missed the obvious approach :/ Call like `f([3 1;0 0;1 4], [2 4 1])`.
> 6 votes

# Answer
# MATLAB / Octave, ~~18~~ 16 bytes

## Thanks to user beaker and Don Muesli for removing 2 bytes!

Given that the coordinates are in a `N x 2` matrix `x` where the first column is the X coordinate and the second column is the Y coordinate, and the masses are in a `1 x N` matrix `y` (or a row vector):

```
@(x,y)y*x/sum(y)

```

The explanation of this code is quite straight forward. This is an anonymous function that takes in the two inputs `x` and `y`. We perform the weighted summation (the numerator expression of each coordinate) in a linear algebra approach using matrix-vector multiplication. By taking the vector `y` of masses and multiplying this with the matrix of coordinates `x` by matrix-vector multiplication, you would compute the weighted sum of both coordinates individually, then we divide each of these coordinates by the sum of the masses thus finding the desired centre of mass returned as a 1 x 2 row vector for each coordinate respectively.

# Example runs

```
>> A=@(x,y)y*x/sum(y)

A =

    @(x,y)y*x/sum(y)

>> x = [0 2; 3 4; 0 1; 1 1];
>> y = [2 6 2 10];
>> A(x,y)

ans =

    1.4000    2.0000

>> x = [3 1; 0 0; 1 4];
>> y = [2 4 1];
>> A(x,y)

ans =

    1.0000    0.8571

```

# Try it online!

https://ideone.com/BzbQ3e
> 6 votes

# Answer
## CJam, 14 bytes

```
{_:+df/.f*:.+}

```

An unnamed function with expects the list of coordinate pairs and the list of masses on the stack (in that order) and leaves the centre of mass in their place.

Test it here.

### Explanation

```
_    e# Duplicate list of masses.
:+d  e# Get sum, convert to double.
f/   e# Divide each mass by the sum, normalising the list of masses.
.f*  e# Multiply each component of each vector by the corresponding weight.
:.+  e# Element-wise sum of all weighted vectors.

```
> 5 votes

# Answer
# Perl 6, ~~36~~ ~~33~~ 30 bytes

```
{[Z+](@^a Z»*»@^b) X/sum @b}

```
> 5 votes

# Answer
## Seriously, 16 bytes

```
╩2└Σ;╛2└*/@╜2└*/

```

Takes input as `[x-coords]\n[y-coords]\n[masses]`, and outputs as `xbar\nybar`

Try it online!

Explanation:

```
╩2└Σ;╛2└*/@╜2└*/
╩                 push each line of input into its own numbered register
 2└Σ;             push 2 copies of the sum of the masses
     ╛2└*/        push masses and y-coords, dot product, divide by sum of masses
          @       swap
           ╜2└*/  push masses and x-coords, dot product, divide by sum of masses

```
> 4 votes

# Answer
## Haskell, ~~55~~ 50 bytes

```
z=zipWith
f a=map(/sum a).foldr1(z(+)).z(map.(*))a

```

This defines a binary function `f`, used as follows:

```
> f [1,2] [[1,2],[3,4]]
[2.3333333333333335,3.333333333333333]

```

See it pass both test cases.

## Explanation

Haskell is not well suited for processing multidimensional lists, so I'm jumping through some hoops here. The first line defines a short alias for `zipWith`, which we need twice. Basically, `f` is a function that takes the list of weights `a` and produces `f a`, a function that takes the list of positions and produces the center of mass. `f a` is a composition of three functions:

```
z(map.(*))a      -- First sub-function:
z         a      --   Zip the list of positions with the mass list a
  map.(*)        --   using the function map.(*), which takes a mass m
                 --   and maps (*m) over the corresponding position vector
foldr1(z(+))     -- Second sub-function:
foldr1           --   Fold (reduce) the list of mass-times-position vectors
       z(+)      --   using element-wise addition
map(/sum a)      -- Third sub-function:
map              --   Map over both coordinates:
   (/sum a)      --     Divide by the sum of all masses

```
> 3 votes

# Answer
## JavaScript (ES6), 60 bytes

```
a=>a.map(([x,y,m])=>{s+=m;t+=x*m;u+=y*m},s=t=u=0)&&[t/s,u/s]

```

Accepts an array of (x, y, mass) "triples" and returns a "tuple".
> 3 votes

# Answer
# R, ~~32~~ 25 bytes

```
function(a,m)m%*%a/sum(m)

```

*edit -7 bytes by switch to matrix algebra (thanks @Sp3000 Julia answer)*

pass an array (matrix with 2 columns, x,y) as coordinates and vector `m` of weights, returns an array with the required coordinates
> 3 votes

# Answer
## PHP, 142 bytes

```
function p($q,$d){return$q*$d;}function c($f){$s=array_sum;$m=array_map;$e=$f[0];return[$s($m(p,$e,$f[1]))/$s($e),$s($m(p,$e,$f[2]))/$s($e)];}

```
**Exploded view**
```
function p($q, $d) {
  return $q * $d;
}

function c($f) {
  $s = array_sum;
  $m = array_map;
  $e = $f[0];
  return [ $s($m(p,$e,$f[1])) / $s($e),
           $s($m(p,$e,$f[2])) / $s($e) ];
}

```
**Required input**
```
Array[Array]: [ [ mass1, mass2, ... ],
                [ xpos1, xpos2, ... ],
                [ ypos1, ypos2, ... ] ]

```
**Return**

`Array: [ xbar, ybar ]`

---

The `p()` function is a basic map, multiplying each `[m]` value with the corresponding `[x]` or `[y]` value. The `c()` function takes in the `Array[Array]`, presents the `array_sum` and `array_map` functions for space, then calculates `Σmx/Σm` and `Σmy/Σm`.

Might be possible to turn the calculation itself into a function for space, will see.
> 2 votes

# Answer
# Mathcad, 8 "bytes"

I don't know what I wasn't thinking of in my previous answer. Here's a shorter way making proper use of matrix multiplication. The variable p contains the data - if setting the variable counts towards the total, then add another 2 "bytes" (creation of input table = 1 byte, variable name = 1 byte).
> 2 votes

# Answer
## Python 3,  ~~95~~ ~~90~~ 88 bytes

## Solution

```
lambda c,m:list(map(sum,zip(*[[i[0]*j/sum(m),i[1]*j/sum(m)]for i,j in zip(*([c,m]))])))

```

## Results

```
>>> f([[0,2],[3,4],[0,1],[1,1]],[2,6,2,10])
[1.3999999999999999, 2.0]
>>> f([[3,1],[0,0],[1,4]],[2,4,1])
[1.0, 0.8571428571428571]

```

*thanks to @Zgarb saving 2 bytes*

---

A recursive solution for fun (95 bytes)

```
f=lambda c,m,x=0,y=0,s=0:f(c[1:],m[1:],x+c[0][0]*m[0],y+c[0][1]*m[0],s+m[0])if c else[x/s,y/s]

```

**Results**

```
>>> f([[0,2],[3,4],[0,1],[1,1]],[2,6,2,10])
[1.4, 2.0]
>>> f([[3,1],[0,0],[1,4]],[2,4,1])
[1.0, 0.8571428571428571]

```
> 1 votes

# Answer
## Python 3, 63 bytes

```
lambda a,b:[sum(x*y/sum(b)for x,y in zip(L,b))for L in zip(*a)]

```

Vector operations on lists is long :/

This is an anonymous lambda function - give it a name and call like `f([[0,2],[3,4],[0,1],[1,1]],[2,6,2,10])`.
> 1 votes

# Answer
# Axiom, 158 bytes

```
c(a:List List Float):List Float==(x:=y:=m:=0.;for i in 1..#a repeat(~index?(3,a.i)=>return[];x:=x+a.i.3*a.i.1;y:=y+a.i.3*a.i.2;m:=m+a.i.3);m=0.=>[];[x/m,y/m])

```

ungolf it

```
-- Input List of Coordinate and masses as [[xi,yi,mi]]
-- Return center of mass for the list a as [x,y] Float coordinates
-- or [] if some error occur [for example masses are all 0]
cc(a:List List Float):List Float==
    x:=y:=m:=0.
    for i in 1..#a repeat
         ~index?(3,a.i)=>return []
         x:=x+a.i.3*a.i.1
         y:=y+a.i.3*a.i.2
         m:=m+a.i.3
    m=0.=>return []
    return[x/m,y/m]

```

results

```
(21) -> c([[0,2,2],[3,4,6],[0,1,2],[1,1,10]])
   (21)  [1.4,2.0]
                                                         Type: List Float
(22) -> c([[3,1,2],[0,0,4],[1,4,1]])
   (22)  [1.0,0.8571428571 4285714286]
                                                         Type: List Float

```
> 0 votes

# Answer
# k, 13 bytes

```
{(+/x*y)%+/y}

```

Try it online!
> 0 votes

---
Tags: code-golf, arithmetic, array
---


title: Shortest 2-Player Game of Halma

text:
# Question
Title: Shortest 2-Player Game of Halma
In Chess, it's possible for the game to end after 4 moves (2 each) with a Fool's Mate.

Your goal is to find the Fool's Mate of Halma: the 2-player game of Halma that minimises the number of turns played.

There are over 1056 board states, and I've seen the branching factor surpass 1000, so chances are no one will find the optimal solution. Instead, you're trying to find the best solution you can.

You should submit a list of moves, and any code you used to generate those moves.

## Explanation of the Game

Halma is similar to Chinese Checkers, but played on a 16\*16 square board.

Initially, the board looks like this:

The goal of the game is to move all your pieces to the starting positions of your opponent's pieces.

On a player's turn, he/she may:

* Pass the turn
* Move one of his/her pieces to an adjacent empty space. Adjacent spaces include diagonals.
* Take one of his/her pieces and do the following any number of times: Jump the piece over an adjacent piece, landing it on the space opposite the piece jumped over.

Here's an example to illustrate the 2nd type of move.

## Rules

Submit a list of legal moves which result in the game ending.

Submit any code you used to generate the list.

If you obtain a better result from someone else's code, post the result in a comment or edit their post with the new results.

Each move must be either `None` to pass the turn, or `(x1,y1,x2,y2)` to move a piece, where `(x1,y1)` are the coordinates of the piece to move and `(x2,y2)` are the destination of that piece (for jump moves, ignore intermediate coordinates). The coordinates start at `(0,0)` at the top left corner. x-coordinates increase to the right, y-coordinates increase downward. Moves should be separated by newlines.

You can use this python script to verify your moves. Use `python halma_verify.py < file` to verify moves in `file`.

Shortest list wins.

# Answer
> 18 votes
# The shortest game of halma is 49 moves

49 move solution

Proof there is no 48-move solution

Code used for this solution

The code now supports pass

Notice that the 47 move solution in the paper is for the army transfer problem, not for the shortest game of halma

I'll hopefully get to doing a proper writeup this weekend

---
Tags: optimization, board-game, puzzle-solver
---


title: Meta radiation hardener

text:
# Question
Title: Meta radiation hardener
## Background

On this site, we occasionally have questions requiring programs to be "radiation hardened"; this means that the program has to be able to survive the deletion of one or more bytes, no matter which bytes are deleted.

As is common for tasks that frequently get set in programming challenges, it's natural to want to make a language that's particularly good at these challenges. Given that the natural way to make this is to add some metadata that makes it possible to reverse corruption, it's actually not really a language that needs designing, but an encoding; the idea is to transform each input to a sequence of bytes, in such a way that even if the sequence is slightly irradiated, it's possible to extract the original input.

## The task

Write two programs or functions, E (an encoder) and D (a decoder), such that:

* E takes two arguments, a sequence of octets (which we'll call "*input*" in this specification) and a nonnegative integer "*radiation*", and outputs a sequence of octets "*encoding*";
* D takes one argument, a sequence of octets ("*encdng*"), and outputs a sequence of octets "*reconstruction*";
* If you run both E and D (with *encdng*, the input to D, chosen by deleting no more than *radiation* elements from *encoding* (not necessarily contiguously)), then *reconstruction* will be equal to *input* no matter which characters were deleted to form *encdng*.

## Clarifications

* If you submit functions, you don't have to call them `E` and `D`; you can choose whatever name is most suitable for your language.
* An "octet" is basically an integer from 0 to 255 inclusive, which you can encode as an integer, a character, or whatever's appropriate for your language.
* E and D must be entirely deterministic (i.e. giving them the same inputs will always produce the same output, where "inputs" is defined as *input* and *radiation* for E, or *encdng* for D). In particular, E may not communicate information to D via a side channel.
* The deletions are performed by deleting one element of the sequence; think of opening the seuqence in an editor, placing the cursor at an arbitrary point, and pressing Backspace. If an element appears multiple times, it's possible that only one copy of the element will be deleted (i.e. other instances of the same octet won't be affected).
* Although the score is only calculated on the basis of fairly short *input*, your program must work in theory for any *input* and *radiation*. In particular, it must work no matter which octets appear in *input*. (Sorry, people who would like the ability to use unprintable characters that they know won't appear in the input, but I need to ensure that the input's incompressible so that the challenge is about radiation hardening rather than compression.)
* You can submit either one file that defines two functions; two files which each define a function or which are both full programs; or three files, two of which implement D and E respectively (either via being full programs or via defining a function), and the third which is a header file or library common to both D and E. Regardless of which form of submission you use, your programming language implementation must be able to understand both programs without further arguments like file locations (or else you must pay a byte penalty for invoking your implementation in an unusual way, as per our standard rules).

## Victory condition

For each *length* and *radiation*, let *f*(*length*,*radiation*) be the total lengths of the *encoding*s that correspond to all *input* with length *length*, and the given *radiation*. (That is, *f*(*length*,*radiation*) = sum*input* has length *length* length(E(*input*,*radiation*)).) Then let *g*(*length*,*radiation*) equal *f*(*length*,*radiation*) ÷ 256*length*. In other words, *g* is the average length of the encoded output, for a given length of input and a given radiation hardening requirement. (In theory you could calculate this by brute force, but it would likely take implausibly long to work out your score that way. I'm expecting most submissions will be able to make a mathematical argument as to what their score is. If you're not sure, post an approximate score and you or someone else can calculate it in more depth if another entry posts a similar score.)

Your score is equal to the sum of *g*(*length*,*radiation*) for all *radiation* in the range 0 to 9 inclusive, and all *length* in the range 0 to 99 inclusive, plus (mostly to avoid hardcoding, or to keep the competition going if someone discovers a mathematically perfect encoding; this is likely to be a minimal factor otherwise) the total number of bytes in your submission to the challenge (plus the standard penalties for things like requiring unusual interpreter flags or specific filenames). The winner is the entry with the lowest score (tiebroken by the first entry to submit).

# Answer
> 8 votes
## CJam, score ≤ 286,516 + 54 + 36 = 286,606

### Encoder

```
{_{1\+_:e>)_0a+@@b0\{{)_256b_,\e`,-}g}*256b+\)e*}{*}?}

```

Try it online!

### Decoder

```
{_{e`1f=(\256b{256b_,\e`,=},,\b1>}&}

```

Try it online!

Both of these take and return a list integers. The TIO links include conversion from/to strings for convenience. Note that these are incredibly inefficient for longer strings. If you want to try a few more characters, I recommend using characters with small character codes.

The basic idea for creating a radiation-hardened encoding involves two steps:

1. Find an encoding which never contains two consecutive identical octets.
2. Repeat each octet in the encoded string **r + 1** times, where **r** is the radiation level.

This way, the radiation can't completely delete one run of identical characters, so that we can decode the string by taking one character from each run and then decoding step 1.

So the only interesting part is finding an encoding that never yields repeated octets. The basic idea is to use something like A043096 as a number system. That is, to encode an integer **N**, we simply count up in some base **b**, skipping all numbers with repeated octets. I believe the amount of numbers that can be represented in this way with up to **d** digits is the same as the amount of numbers that can be represented in bijective base **b-1** (since, when you want to write such a number, you can choose between **b-1** digit for each position without violating the constraint).

Of course, to obtain maximal compression we will use **b = 256**. To turn the input into an integer, we can use base conversion as well. If I wasn't lazy, I'd use a bijective base for the input, but for now I'm just prepending a `1` (to ensure there are no leading zeros) and then use the smallest possible base that such that all octets in the input are less than the base.

This base is then prepended to the encoding (so that the decoder knows which base to use) and separated from the remaining number by a 0-octet (this works because the remaining number will never start with a zero). As a minor optimisation, the empty string remains an empty string.

The reason I haven't computed an exact score above is that I'm only computing an upper bound for how long each input will be based on its length and its maximal octet. However, for these two parameters, there will often be two different output lengths, and I haven't bothered figuring out yet where the tipping point between them occurs. I've also used the length of usual base 255 instead of bijective base 255 to estimate that length, which is again slightly bigger than it needs to be. The exact Mathematica code I used for the computation is the following:

```
num[l_, 1] = 0;
num[l_, base_] := num[l, base] = base^l - Sum[num[l, b], {b, base - 1}]
Sum[
  num[l, b]*(r + 1)*(2 + IntegerLength[2*b^l - 1, 255])/256^l,
  {r, 0, 9}, {l, 1, 99}, {b, 2, 256}
]
N@%

```

`num[l, b]` should give the the number of strings of length `l` with maximum octet `b-1` (except for `b == 1`, where I've hardcoded it to `0` because I'm always using at least base `2`).

# Answer
> 6 votes
# bash + GNU utilities, score ~~294506~~ 283468

*Edit 1: Fixes a problem that @Leo noticed -- thank you!*

*Edit 2: Improved the encoding method for the radiation parameter, for a better score.*

Encoder (97 bytes):

```
for((j=0;j<$1;j++)){ p+=p\;;}
(sed 's/\(.\)\1/\1a\1a/g'<<<$1;cat)|xxd -p -c1|sed ${p-;}|xxd -r -p

```

Decoder (121 bytes):

```
read n
n=`sed 's/\(.\)\1*/\1/g'<<<$n`
sed -r "s/( ..)\1{0,${n//a}}/\1/g"<<<' 0a '`xxd -p -c1`|sed 's/^ [^ ]*//'|xxd -r -p

```

For the encoder: Octet sequence passed as characters in stdin, radiation parameter r passed as an argument.

For the decoder: Input passed as characters in stdin.

For both: Output on stdout.

The encoder prepends to the input data the digits of r, with a character 'a' inserted between each pair of consecutive identical digits, followed by a single newline. It then copies all the input (starting with the prepended characters), replacing each character by r+1 copies of that character.

The decoder undoes this, going through each of the remaining characters x in its input, skipping up to r consecutive identical copies of x following x, and printing what remains. The prepended data has no repeated characters, so it can be decoded before r is known. At that point, r is known, and that value is needed to decode the rest of the data correctly.

You can check that this works even if the original input has repeated identical characters.

---

Score computation:

Suppose the input has length L and the radiation parameter is r (which is at most 9 for the scoring computation, so it fits in one digit and therefore has no consecutive repeated characters). The prepended data is 2 bytes (digit, newline), so the output is (r+1)(L+2) bytes for the encoded stream.

So g(L,r) = (r+1)(L+2).

It follows that the total score can be computed as

# Answer
> 3 votes
# Perl + Math::{ModInt, Polynomial, Prime::Util}, score ≤ 92819

```
$m=Math::Polynomial;sub l{($n,$b,$d)=@_;$n||$d||return;$n%$b,l($n/$b,$b,$d&&$d-1)}sub g{$p=$m->interpolate([grep ref$_[$_],0..$map{$p->evaluate($_)}0..$}sub p{prev_prime(128**$s)}sub e{($_,$r)=@_;length||return'';$s=$r+1;s/^[␀␁]/␁$&/;@l=map{mod($_,p$s)}l(Math::BigInt->from_bytes($_),p$s);$@l+$r>p($s)&&return e($_,$s);$a=0;join'',map{map{chr$_+$a}l($_->residue,128,$s,($a^=128))}g(@l)}sub d{@l=split/([␀-␡]+)/,$_[0];@l||return'';$s=vecmax map length,@l;@l=g map{length==$s&&mod($m->new(map{ord()%128}split//)->evaluate(128),p$s)}@l;$$_=$m->new(map{$_->residue}@l)->evaluate(p$s)->to_bytes;s/^␁//;$_}

```

Control pictures are used to represent the corresponding control character (e.g.  is a literal NUL character). Don't worry much about trying to read the code; there's a more readable version below.

Run with `-Mbigint -MMath::ModInt=mod -MMath::Polynomial -MNtheory=:all`. `-MMath::Bigint=lib,GMP` is not necessary (and thus not included in the score), but if you add it before the other libraries it'll make the program run somewhat faster.

## Score calculation

The algorithm here is somewhat improvable, but would be rather harder to write (due to Perl not having the appropriate libraries). Because of this, I made a couple of size/efficiency tradeoffs in the code, on the basis that given that bytes can be saved in the encoding, there's no point in trying to shave off every point from golfing.

The program consists of 600 bytes of code, plus 78 bytes of penalties for command-line options, giving a 678 point penalty. The rest of the score was calculated by running the program on the best-case and worst-case (in terms of output length) string for every length from 0 to 99 and every radiation level from 0 to 9; the average case is somewhere in between, and this gives bounds on the score. (It's not worth trying to calculate the exact value unless another entry comes in with a similar score.)

This therefore means that the score from encoding efficiency is in the range 91100 to 92141 inclusive, thus the final score is:

### 91100 + 600 + 78 = 91778 ≤ score ≤ 92819 = 92141 + 600 + 78

## Less-golfed version, with comments and test code

This is the original program + newlines, indentation, and comments. (Actually, the golfed version was produced by removing newlines/indentation/comments from this version.)

```
use 5.010;                    # -M5.010; free
use Math::BigInt lib=>'GMP';  # not necessary, but makes things much faster
use bigint;                   # -Mbigint
use Math::ModInt 'mod';       # -MMath::ModInt=mod
use Math::Polynomial;         # -MMath::Polynomial
use ntheory ':all';           # -Mntheory=:all
use warnings;                 # for testing; clearly not necessary

### Start of program

$m=Math::Polynomial;          # store the module in a variable for golfiness

sub l{ # express a number $n in base $b with at least $d digits, LSdigit first
    # Note: we can't use a builtin for this because the builtins I'm aware of
    # assume that $b fits into an integer, which is not necessarily the case.
    ($n,$b,$d)=@_;
    $n||$d||return;
    $n%$b,l($n/$b,$b,$d&&$d-1)
}

sub g{ # replaces garbled blocks in the input with their actual values
    # The basic idea here is to interpolate a polynomial through all the blocks,
    # of the lowest possible degree. Unknown blocks then get the value that the
    # polynomial evaluates to. (This is a special case of Reed-Solomon coding.)
    # Clearly, if we have at least as many ungarbled blocks as we did original
    # elements, we'll get the same polynomial, thus we can always reconstruct
    # the input.
    # Note (because it's confusing): @_ is the input, $_ is the current element
    # in a loop, but @_ is written as $_ when using the [ or # operator (e.g.
    # $_[0] is the first element of @_.
    # We waste a few bytes of source for efficiency, storing the polynomial
    # in a variable rather than recalculating it each time.
    $p=$m->interpolate([grep ref$_[$_],0..$#_],[grep ref,@_]);
    # Then we just evaluate the polynomial for each element of the input.
    map{$p->evaluate($_)}0..$#_
}

sub p{ # determines maximum value of a block, given (radiation+1)
    # We split the input up into blocks. Each block has a prime number of
    # possibilities, and is stored using the top 7 bits of (radiation+1)
    # consecutive bytes of the output. Work out the largest possible prime that
    # satisfies this property.
    prev_prime(128**$s)
}

sub e{ # encoder; arguments: input (bytestring), radiation (integer)
    ($_,$r)=@_; # Read the arguments into variables, $_ and $r respectively
    length||return''; # special case for empty string
    $s=$r+1; # Also store radiation+1; we use it a lot
    # Ensure that the input doesn't start with NUL, via prepending SOH to it if
    # it starts with NUL or SOH. This means that it can be converted to a number
    # and back, roundtripping correctly.
    s/^[␀␁]/␁$&/; #/# <- unconfuse Stack Exchange's syntax highlighting
    # Convert the input to a bignum, then to digits in base p$s, to split it
    # into blocks.
    @l=map{mod($_,p$s)}l(Math::BigInt->from_bytes($_),p$s);
    # Encoding can reuse code from decoding; we append $r "garbled blocks" to
    # the blocks representing the input, and run the decoder, to figure out what
    # values they should have.
    $#l+=$r;
    # Our degarbling algorithm can only handle at most p$s blocks in total. If
    # that isn't the case, try a higher $r (which will cause a huge increase in
    # $b and a reduction in @l).
    @l+$r>p($s)&&return e($_,$s);
    # Convert each block to a sequence of $s digits in base 128, adding 128 to
    # alternating blocks; this way, deleting up to $r (i.e. less than $s) bytes
    # will preserve the boundaries between each block; then convert that to a
    # string
    $a=0; # we must initialize $a to make this function deterministic
    join'',map{map{chr$_+$a}l($_->residue,128,$s,($a^=128))}g(@l)
}

sub d{ # decoder: arguments; encdng (bytestring)
    # Reconstruct the original blocks by looking at their top bits
    @l=split/([␀-␡]+)/,$_[0];
    @l||return''; # special case for empty string
    # The length of the longest block is the radiation parameter plus 1 (i.e.
    # $s). Use that to reconstruct the value of $s.
    $s=vecmax map length,@l;
    # Convert each block to a number, or to undef if it has the wrong length.
    # Then work out the values for the undefs.
    @l=g map{
        # Convert blocks with the wrong length to undef.
        length==$s&&
            # Convert other blocks to numbers, via removing any +128 and then
            # using Math::Polynomial to convert the digit list to a number.
            mod($m->new(map{ord()%128}split// #/# <- fix syntax highlighting
            )->evaluate(128),p$s)
    }@l;
    # Remove the redundant elements at the end; now that they've reconstructed
    # the garbled elements they have no further use.
    $#l-=$s-1;
    # Convert @l to a single number (reversing the conversion into blocks.)
    $_=$m->new(map{$_->residue}@l)->evaluate(p$s)
        # Convert that number into a string.
        ->to_bytes;
    # Delete a leading SOH.
    s/^␁//;  #/# <- unconfuse Stack Exchange's syntax highlighting
    # Finally, return the string.
    $_
}

### Testing code
use Encode qw/encode decode/;

# Express a string using control pictures + IBM437, to make binary strings
# easier for a human to parse
sub format_string {
    ($_)=@_;
    $_ = decode("Latin-1", $_);
    s/[\0-\x1f]/chr (0x2400 + ord $&)/eag;
    s/\x7f/chr 0x2421/eag;
    s/[ -~\x80-\xff]/decode("IBM437",$&)/eag;
    encode("UTF-8","\x{ff62}$_\x{ff63}")
}

sub test {
    my ($string, $radiation, $samples) = @_;
    say "Input: ", format_string($string);
    my $encoding = e($string, $radiation);
    say "Encoding: ", format_string($encoding);
    say "Input length ", length($string), ", encoding length ", length($encoding), ", radiation $radiation";
    my $decoding = d($encoding);
    $decoding eq $string or die "Mistake in output!";
    say "Decoding: ", format_string($decoding), " from ",
        format_string($encoding);

    # Pseudo-randomly generate $samples radiation-damaged versions.
    srand 1;
    for my $i (1..$samples) {
        my $encdng = $encoding;
        for my $r (1..$radiation) {
            substr $encdng, int(rand(length $encdng)), 1, "";
        }
        my $newdecoding = d($encdng);
        say "Decoding: ", format_string($newdecoding), " from ",
            format_string($encdng);
        $newdecoding eq $string or die "Mistake in output!";
    }

    say "";
    length $encoding;
}

test "abcdefghijklm", 1, 10;
test "abcdefghijklm", 2, 10;
test "abcdefghijklm", 5, 10;
test "abcdefghijklm", 10, 10;
test "\0\0\0\0\0", 1, 10;
test "\5\4\3\2\1", 2, 10;
test "a", 10, 10;

my %minlength = ();
my %maxlength = ();

for my $length (0..99) {
    my ($min, $max) = ("", "");
    $length and ($min, $max) =
        ("\2" . "\0" x ($length - 1), "\1" . "\377" x ($length - 1));
    for my $radiation (0..9) {
        $minlength{"$length-$radiation"} = test $min, $radiation, 1;
        $maxlength{"$length-$radiation"} = test $max, $radiation, 1;
    }
}

say "Minimum score: ", vecsum values %minlength;
say "Maximum score: ", vecsum values %maxlength;

```

## Algorithm

### Simplifying the problem

The basic idea is to reduce this "deletion coding" problem (which is not a widely-explored one) into an erasure coding problem (a comprehensively explored area of mathematics). The idea behind erasure coding is that you're preparing data to be sent over an "erasure channel", a channel that sometimes replaces the characters it sends with a "garble" character that indicates a known position of an error. (In other words, it's always clear where corruption has occurred, although the original character is still unknown.) The idea behind that is pretty simple: we divide the input up into blocks of length (*radiation* \+ 1), and use seven out of the eight bits in each block for data, whilst the remaining bit (in this construction, the MSB) alternates between being set for an entire block, clear for the entire next block, set for the block after that, and so on. Because the blocks are longer than the radiation parameter, at least one character from each block survives into the output; so by taking runs of characters with the same MSB, we can work out which block each character belonged to. The number of blocks is also always greater than the radiation parameter, so we always have at least one undamaged block in the encdng; we thus know that all blocks that are longest or tied for longest are undamaged, allowing us to treat any shorter blocks as damaged (thus a garble). We can also deduce the radiation parameter like this (it's the length of an undamaged block, minus 1).

### Erasure coding

As for the erasure coding part of the problem, this uses a simple special case of the Reed-Solomon construction. This is a systematic construction: the output (of the erasure coding algorithm) is equal to the input plus a number of extra blocks, equal to the radiation parameter. We can calculate the values needed for these blocks in a simple (and golfy!) way, via treating them as garbles, then running the decoding algorithm on them to "reconstruct" their value.

The actual idea behind the construction is also very simple: we fit a polynomial, of the minimum possible degree, to all the blocks in the encoding (with garbles interpolated from the other elements); if the polynomial is *f*, the first block is *f*(0), the second is *f*(1), and so on. It's clear that the degree of the polynomial will equal the number of blocks of input minus 1 (because we fit a polynomial to those first, then use it to construct the extra "check" blocks); and because *d*+1 points uniquely define a polynomial of degree *d*, garbling any number of blocks (up to the radiation parameter) will leave a number of undamaged blocks equal to the original input, which is enough information to reconstruct the same polynomial. (We then just have to evaluate the polynomial to ungarble a block.)

### Base conversion

The final consideration left here is to do with the actual values taken by the blocks; if we do polynomial interpolation on the integers, the results may be rational numbers (rather than integers), much larger than the input values, or otherwise undesirable. As such, instead of using the integers, we use a finite field; in this program, the finite field used is the field of integers modulo *p*, where *p* is the largest prime less than 128*radiation*+1 (i.e. the largest prime for which we can fit a number of distinct values equal to that prime into the data part of a block). The big advantage of finite fields is that division (except by 0) is uniquely defined and will always produce a value within that field; thus, the interpolated values of the polynomials will fit into a block just the same way that the input values do.

In order to convert the input into a series of block data, then, we need to do base conversion: convert the input from base 256 into a number, then convert into base *p* (e.g. for a *radiation* parameter of 1, we have *p* = 16381). This was mostly held up by Perl's lack of base conversion routines (Math::Prime::Util has some, but they don't work for bignum bases, and some of the primes we work with here are incredibly large). As we're already using Math::Polynomial for polynomial interpolation, I was able to reuse it as a "convert from digit sequence" function (via viewing the digits as the coefficients of a polynomial and evaluating it), and this works for bignums just fine. Going the other way, though, I had to write the function myself. Luckily, it isn't too hard (or verbose) to write. Unfortunately, this base conversion means that the input is typically rendered unreadable. There's also an issue with leading zeroes; this program uses the simple (but not perfectly efficient) method of prepending a 1 octet to the program if it starts with a 0 or 1 octet (and reversing the translation when decoding), thus avoiding the issue altogether.

It should be noted that we can't have more than *p* blocks in the output (otherwise the indexes of two blocks would become equal, and yet possibly need to produce different outputs form the polynomial). This only happens when the input is extremely large. This program solves the issue in a very simple way: increasing *radiation* (which makes the blocks larger and *p* much larger, meaning we can fit much more data in, and which clearly leads to a correct result).

One other point worth making is that we encode the null string to itself, because the program as written would crash on it otherwise. It's also clearly the best possible encoding, and works no matter what the radiation parameter is.

## Potential improvements

The main asymptotic inefficiency in this program is to do with the use of modulo-prime as the finite fields in question. Finite fields of size 2n exist (which is exactly what we'd want here, because the blocks' payload sizes are naturally a power of 128). Unfortunately, they're rather more complex than a simple modulo construction, meaning that Math::ModInt wouldn't cut it (and I couldn't find any libraries on CPAN for handling finite fields of non-prime sizes); I'd have to write an entire class with overloaded arithmetic for Math::Polynomial to be able to handle it, and at that point the byte cost might potentially overweigh the (very small) loss from using, e.g., 16381 rather than 16384.

Another advantage of using power-of-2 sizes is that the base conversion would become much easier. However, in either case, a better method of representing the length of the input would be useful; the "prepend a 1 in ambiguous cases" method is simple but wasteful. Bijective base conversion is one plausible approach here (the idea is that you have the base as a digit, and 0 as not a digit, so that each number corresponds to a single string).

Although the asymptotic performance of this encoding is very good (e.g. for an input of length 99 and a radiation parameter of 3, the encoding is always 128 bytes long, rather than the ~400 bytes that repetition-based approaches would get), its performance is less good on short inputs; the length of the encoding is always at least the square of the (radiation parameter + 1). So for very short inputs (length 1 to 8) at radiation 9, the length of the output is nonetheless 100. (At length 9, the length of the output is sometimes 100 and sometimes 110.) Repetition-based approaches clearly beat this erasure-coding-based approach on very small inputs; it might be worth changing between multiple algorithms based on the size of the input.

Finally, it doesn't really come up in the scoring, but with very high radiation parameters, using a bit of every byte (⅛ of the output size) to delimit blocks is wasteful; it would be cheaper to use delimiters between the blocks instead. Reconstructing the blocks from delimiters is rather harder than with the alternating-MSB approach, but I believe it to be possible, at least if the data is sufficiently long (with short data, it can be hard to deduce the radiation parameter from the output). That would be something to look at if aiming for an asymptotically ideal approach regardless of the parameters.

(And of course, there could be an entirely different algorithm that produces better results than this one!)

---
Tags: code-challenge, metagolf, hashing, radiation-hardening
---


title: Help me sort out my desktop windows!

text:
# Question
Title: Help me sort out my desktop windows!
It's really frustrating when I'm working and I have a ton of windows open that are completely or partially hidden behind other windows. To make things worse, I'm still using two 1024x768 monitors.

Your task is to take a list of coordinates that designate the area, in pixels, on a screen, that a list of windows occupy and output a truthy value if, for a 2 monitor set-up with 1024x768 resolution, all the following conditions are met:

* None of the windows would overlap,
* None of the windows would be partly off screen
* None of the windows would straddle a boundary between the two monitors (so the order in which you visualize monitors 1 and 2 is irrelevant)

And a falsey value if any of these criteria are not met.

You may assume that all windows are rectangular, and that no coordinates are negative in the input, which is in a file, in stdin, or in a list of tuples, is in the following format:

```
monitor-number left-x bottom-y right-x top-y
monitor-number left-x bottom-y right-x top-y
monitor-number left-x bottom-y right-x top-y

```

Where each line contains the ID of the monitor (which can either be in `[1, 2]` or `[0, 1]` depending on which is easier for your language), and the dimensions of a window.

For example, the following input will result in a truthy output because none of the windows overlap:

```
1 10 10 100 200
1 210 300 600 600
2 10 10 100 200

```

The following input will result in a falsey value because lines 1 and 3 result in an overlap:

```
1 10 10 50 50
2 5 5 600 200
1 20 20 80 80

```

The following input will result in a falsey value because it would partially off-screen on one of the monitors:

```
1 1000 400 1400 300

```

This is so the shortest solution wins.

# Answer
# Jelly, 33 bytes

```
<⁽¡ð,769FẠ
Ḋs2Zr/€p/;€Ḣµ€ẎµQL⁼LȧÇ

```

A monadic link taking a list of lists of the window-data and returning `0` if any windows exceed their monitor's space or overlap, or `1` otherwise.

Uses 1-indexed monitor IDs; `1,1` to `1024,768` inclusive are considered on-screen.

**Try it online!** (Too slow for the first two test cases! Typical golf :))

### How?

The reason this is so slow is because it creates all the pixels for all the windows, each with its monitor ID and checks for overlap using de-duplication (which is implemented using lists not sets). It also checks each pixel is on-screen rather than checking just the input corners. All in all very inefficient...

Test-case 1 succeeded (`1`) locally in **only** eleven minutes! Test-case 2 succeeded (`0`) in less.

```
<⁽¡ð,769FẠ - Link 1 check pixels are on-screen: list of lists, each being [x,y,ID]
 ⁽¡ð       - literal base-250 integer = 1025
    ,769   - pair with literal 769
<          - less than (vectorises) -> [[x<1025, y<769, ID],...]
        F  - flatten into a single list
         Ạ - all truthy?

Ḋs2Zr/€p/;€Ḣµ€ẎµQL⁼LȧÇ - Main link: list of lists, each being [ID,Lx,By,Rx,Ty]
            µ€         - for €ach window:
Ḋ                      -   dequeue -> [Lx,By,Rx,Ty]
 s2                    -   split into twos -> [[Lx,By],[Rx,Ty]]
   Z                   -   transpose -> [[Lx,Rx],[By,Ty]]
     /€                -   reduce €ach with:
    r                  -     inclusive range -> [[Lx,...,Rx],[By,...,Ty]]
        /              -   reduce with:
       p               -     Cartesian product -> all pixels, [[Lx,By],[Lx,By+1],...[Lx,Ty],[Lx+1,By],... ...[Rx,Ty]]
           Ḣ           -   head -> ID
         ;€            -   concatenate each pixel with the monitor ID
              Ẏ        - tighten -> one list of all window's [x,y,ID] values
               µ       - monadic chain separation, call that w
                Q      - deduplicate (unique [x,y,ID] values)
                 L     - length
                   L   - length of w
                  ⁼    - equal?
                     Ç - call last link (1) as a monad (all on-screen?)
                    ȧ  - logical and

```
> 4 votes

# Answer
## Haskell, ~~103~~ 88 bytes

```
f l=[]==[a|z@(m,a,b,c,d)<-l,y@(n,e,f,g,h)<-l,y/=z&&m==n&&e<c&&(b<h||f<d)||1024<c||768<d]

```

Forgot the bounds checking initially.

Takes input as a list of 5-tuples representing the windows.

### How does it work?

We pair all windows with each other and then look at all pairs `(a, b)` with `a /= b`. Since the relation is symmetric, we only have to check whether the right end of the first and left end of the second window overlap. If they do, then for them to overlap one's lower has to be higher than the other one's top or vice versa. Lastly, we do bounds checking.

If any of the conditions are true, the list will contain more than one element, so all there is left to do is to check whether the list is empty.
> 2 votes

# Answer
## JavaScript (ES6), 100 bytes

```
a=>!a.some(([m,l,b,r,t],i)=>l<0|b<0|r>1024|t>768|a.some(([n,k,c,s,u],j)=>i!=j&m==n&l<s&b<u&r>k&t>c))

```

Takes input as an array of arrays. Assumes window coordinates are monitor-relative. I could save 8 bytes by assuming windows never overlap to the left of the monitor but 100 is a nice round number ;-)
> 1 votes

---
Tags: code-golf, number, geometry
---


title: Splix.io - King of the land

text:
# Question
Title: Splix.io - King of the land
**You are an enterprising dot** who wants to increase the land under its control. This is quite simple - travel outside your current land and loop back into your land and everything in that loop is now owned by you. But there is a catch. If some other dot somehow finds your loop and crosses it, you die.

If you haven't already tried it, go to Splix.io and try a game. Use the arrow keys to control your movement.

GIF

Credit: http://splix.io/

## Specifics

All players start at random positions on a 200x200 board. (I reserve the right to change this :). You will have a certain amount of moves to amass the greatest number of points possible. Points are tallied by:

* The number of players you have killed times 300
* The amount of land you own at the end of the round

This brings up the point that others can steal your land. If they start a loop that intersects some of your land, they can claim it. If you die during the round, you lose all points for that round.

Each round has a randomly selected group of players (max 5 unique players) (subject to change). Every player participates in an equal number of rounds. Your bot's final score is determined by its average per-game score. Each game consists of 2000 turns (also subject to change). All bots make their moves at the same time.

### Death Cases

**Head Butt**

Both players die when they head butt each other. This is still true even when both players are at the edge of their space.

However, when only one of the players is in his land, the other player dies.

**Line Cross**

In this case, only the purple player dies.

You can't cross your own line.

**Exiting the board**

If a player attempts to exit the board, he will die and lose all points.

### Capturing area

A player will capture area when he has a trail and he enters his own land again.

Red fills in between the two red lines. The only case where a player does not fill in is when another player is inside the loop. To be clear, this only applies when the other player himself is in the loop, not just land owned by him. A player can capture land from another person. If a player cannot fill in the area surrounded by his trail, the trail is converted directly to normal land. If the player inside another players land loop dies, the area in that loop is filled. Every time a player dies, the board is reexamined for an area that can be filled in.

## Controller details

The controller is here. It is very similar to the original game, but small changes have been made to make this a better fit for KotH and for technical reasons. It is built with @NathanMerrill's KotHComm library, and with substantial help from @NathanMerrill as well. Please let me know of any bugs you find in the controller in the chat room. To be consistent with KotHComm, I have used Eclipse collections throughout the controller, but bots can be written using only the Java Collections library.

Everything is packaged in an uberjar on the github releases page. To use it, download it and attach it to your project so you can use it for auto-compleat (instructions for IntelliJ, Eclipse). To test your submissions, you run the jar with `java -jar SplixKoTH-all.jar -d path\to\submissions\folder`. Ensure that `path\to\submissions\folder` has a subfoler named `java`, and to place all your files there. Do not use package names in your bots (although it may be possible with KotHComm, it's just a bit more trouble). To see all options, use `--help`. To load all the bots, use `--question-id 126815`.

## Writing a bot

To start writing a bot, you must extend **`SplixPlayer`**.

* `Direction makeMove(ReadOnlyGame game, ReadOnlyBoard board)`
    + This is where you decide which move you want your bot to make. Must not return null.
* `HiddenPlayer getThisHidden()`
    + Get the **`HiddenPlayer`** version of `this`. Useful for comparing your bot to the board.

### `enum Direction`

* Values
    + `East` *(x = 1; y = 0)*
    + `West` *(x = -1; y = 0)*
    + `North` *(x = 0; y = 1)*
    + `South` *(x = 0; y = -1)*
* `Direction leftTurn()`
    + Get the **`Direction`** that you would get if you made a left turn.
* `Direction RightTurn()`
    + Get the **`Direction`** that you would get if you made a right turn.

### `ReadOnlyBoard`

This is the class where you access the board. You can either get a local view (20x20) of the board with the player positions shown, or a global view (the entire board) with only the information of who owns and claims positions on the board. This is also where you get your position.

* `SquareRegion getBounds()`
    + Retrieve the size of the board.
* `MutableMap<com.nmerrill.kothcomm.game.maps.Point2D,ReadOnlySplixPoint> getGlobal()`
    + Get a global map of the board.
* `MutableMap<com.nmerrill.kothcomm.game.maps.Point2D,ReadOnlySplixPoint> getView()`
    + Same as `getGlobal()`, except that it is limited to a 20x20 area around your player, and that it shows player positions.
* `Point2D getPosition(SplixPlayer me)`
    + Get the position of your player. Use as `board.getPosition(this)`.
* `Point2D getSelfPosition(ReadOnlyBoard)`
    + Get your position on the board. Usage: `Point2D mypos = getSelfPosition(board)`

### `ReadOnlyGame`

`ReadOnlyGame` only provides access to the number of turns left in the game through `int getRemainingIterations()`.

### `ReadOnlySplixPoint`

* `HiddenPlayer getClaimer()`
    + Get the `HiddenPlayer` version of who is claiming a point - claiming = a trail.
* `HiddenPlayer getOwner()`
    + Get who owns a point.
* `HiddenPlayer getWhosOnSpot()`
    + If the player is positioned on this point, return the hidden version of it. Only works in `getLocal()`.

### `Point2D`

Unlike the other classes here, `Point2D` is contained in the KotHComm library. `com.nmerrill.kothcomm.game.maps.Point2D`

* `Point2D(int x, int y)`
* `int getX()`
* `int getY()`
* `Point2D moveX(int x)`
* `Point2D moveY(int y)`
* `Point2D wrapX(int maxX)`
    + Wrap the `x` value to be within the range of `maxX`.
* `Point2D wrapY(int maxY)`
    + Wrap the `y` value to be within the range of `maxY`.
* `int cartesianDistance(Point2D other)`
    + This translates to how many turns it would take for a player to move from point a to point b.

## Clojure support

The Clojure compiler is bundled with the `SplixKoTH-all.jar`, so you can use Clojure for your bot! Refer to my `random_bot` to see how to use it.

## Debugging a bot

The controller comes with a debugger to help test strategies. To start it, run the jar with the `--gui` option.

To attach the debugger to your jar, follow these instructions for IntelliJ, or these instructions for Eclipse (Eclipse version untested).

If you are using a debugger with your code, you can use this to help visualize what your bot is seeing. Set a breakpoint at the beginning of `makeMove` on your bot, and ensure that it only pauses the current thread. Next, click the start button on the UI and step through your code.

Now, to put it all together:

# Running bots

To run your bots with others, you need to run the jar on the releases page. Here is a list of flags:

* `--iterations` (`-i`) \<= `int` (default `500`)
    + Specify the number of games to run.
* `--test-bot` (`-t`) \<= `String`
    + Run only the games that the bot is included in.
* `--directory` (`-d`) \<= Path
    + The directory to run submissions from. Use this to run your bots. Ensure that your bots are a in a subfolder of the path named `java`.
* `--question-id` (`-q`) \<= `int` (only use `126815`)
    + Download and compile the other submissions from the site.
* `--random-seed` (`-r`) \<= `int` (defaults to a random number)
    + Give a seed to the runner so that bots that use random can have results reproduced.
* `--gui` (`-g`)
    + Run the debugger ui instead of running a tournament. Best used with `--test-bot`.
* `--multi-thread` (`-m`) \<= `boolean` (default `true`)
    + Run a tournoment in multi-thread mode. This enables a faster result if your computer has multiple cores.
* `--thread-count` (`-c`) \<= `int` (default `4`)
    + Number of threads to run if multi-thread is allowed.
* `--help` (`-h`)
    + Print a help message similar to this.

To run all the submissions on this page, use `java -jar SplixKoTH-all.jar -q 126815`.

# Formatting your post

To ensure that the controller can download all the bots, you should follow this format.

```
[BotName], Java                     // this is a header
                                    // any explanation you want
[BotName].java                      // filename, in the codeblock
[code]

```

Also, do not use a package declaration.

---

# Scoreboard

```
+------+--------------+-----------+
| Rank | Name         |     Score |
+------+--------------+-----------+
|    1 | ImNotACoward | 8940444.0 |
|    2 | TrapBot      |  257328.0 |
|    3 | HunterBot    |  218382.0 |
+------+--------------+-----------+

```

---

Please let me know if any portion of the rules are unclear, or if you find any errors in the controller in the chat room.

## Have fun!

# Answer
# ImNotACoward, Java

This bot is a ~~coward~~ survival expert. If there is no enemy nearby, he claims a part of the land. If the loop of another player can be reached safely, he ~~stabs the other player in the back~~ engages the other player in a duel. If the other player cannot be attacked safely, he ~~flees~~ performs a strategic retreat to his own land.

```
ImNotACoward.java
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.api.set.MutableSet;
import org.eclipse.collections.impl.factory.Lists;
import org.eclipse.collections.impl.factory.Maps;
import org.eclipse.collections.impl.factory.Sets;

import com.jatkin.splixkoth.ppcg.game.Direction;
import com.jatkin.splixkoth.ppcg.game.SplixPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.HiddenPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyBoard;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyGame;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlySplixPoint;
import com.nmerrill.kothcomm.game.maps.Point2D;
import com.nmerrill.kothcomm.game.maps.graphmaps.bounds.point2D.SquareRegion;

public class ImNotACoward extends SplixPlayer {
    private static final MutableSet<Direction> DIRECTIONS = Sets.mutable.of(Direction.values());

    private static class Board {
        public MutableSet<Point2D> allPoints = null;
        private SquareRegion globalBounds = null;
        private SquareRegion viewBounds = null;
        private MutableMap<Point2D, ReadOnlySplixPoint> global = null;
        private MutableMap<Point2D, ReadOnlySplixPoint> view = null;

        public void update(ReadOnlyBoard readOnlyBoard) {
            if (this.allPoints == null) {
                this.allPoints = readOnlyBoard.getGlobal().keysView().toSet();
                this.globalBounds = readOnlyBoard.getBounds();
            }
            this.viewBounds = readOnlyBoard.viewingArea;
            this.global = readOnlyBoard.getGlobal();
            this.view = readOnlyBoard.getView();
        }

        public boolean inBounds(Point2D point) {
            return globalBounds.inBounds(point);
        }

        public boolean inView(Point2D point) {
            return viewBounds.inBounds(point);
        }

        public ReadOnlySplixPoint getSplixPoint(Point2D point) {
            return inView(point) ? view.get(point) : global.get(point);
        }

        public MutableSet<Point2D> getNeighbors(Point2D point) {
            return DIRECTIONS.collect(d -> point.move(d.vector.getX(), d.vector.getY())).select(this::inBounds);
        }

        public MutableSet<Point2D> getNeighbors(MutableSet<Point2D> points) {
            return points.flatCollect(this::getNeighbors);
        }

        public MutableSet<Point2D> getBorders(SquareRegion region) {
            return allPoints.select(p -> region.inBounds(p) &&
                    (p.getX() == region.getLeft() || p.getX() == region.getRight() ||
                    p.getY() == region.getTop() || p.getY() == region.getBottom() ||
                    p.getX() == globalBounds.getLeft() || p.getX() == globalBounds.getRight() ||
                    p.getY() == globalBounds.getTop() || p.getY() == globalBounds.getBottom()));
        }
    }

    private class Player {
        public final HiddenPlayer hiddenPlayer;
        public MutableSet<Point2D> owned = Sets.mutable.empty();
        private MutableSet<Point2D> unowned = null;
        private MutableSet<Point2D> oldClaimed = Sets.mutable.empty();
        public MutableSet<Point2D> claimed = Sets.mutable.empty();
        private MutableSet<Point2D> oldPos = Sets.mutable.empty();
        public MutableSet<Point2D> pos = Sets.mutable.empty();

        public Player(HiddenPlayer hiddenPlayer) {
            super();
            this.hiddenPlayer = hiddenPlayer;
        }

        public void nextMove() {
            owned.clear();
            unowned = null;
            oldClaimed = claimed;
            claimed = Sets.mutable.empty();
            oldPos = pos;
            pos = Sets.mutable.empty();
        }

        public MutableSet<Point2D> getUnowned() {
            if (unowned == null) {
                unowned = board.allPoints.difference(owned);
            }
            return unowned;
        }

        public void addOwned(Point2D point) {
            owned.add(point);
        }

        public void addClaimed(Point2D point) {
            claimed.add(point);
        }

        public void setPos(Point2D point) {
            pos.clear();
            pos.add(point);
        }

        public void calcPos() {
            if (pos.isEmpty()) {
                MutableSet<Point2D> claimedDiff = claimed.difference(oldClaimed);
                if (claimedDiff.size() == 1) {
                    pos = board.getNeighbors(claimedDiff).select(p -> !claimed.contains(p) && !board.inView(p));
                } else if (!oldPos.isEmpty()) {
                    pos = board.getNeighbors(oldPos).select(p -> owned.contains(p) && !board.inView(p));
                } else {
                    pos = owned.select(p -> !board.inView(p));
                }
            }
        }
    }

    private Board board = new Board();
    private Point2D myPos = null;
    private final Player nobody = new Player(new HiddenPlayer(null));
    private final Player me = new Player(new HiddenPlayer(this));
    private MutableMap<HiddenPlayer, Player> enemies = Maps.mutable.empty();
    private MutableMap<HiddenPlayer, Player> players = Maps.mutable.of(nobody.hiddenPlayer, nobody, me.hiddenPlayer, me);
    private MutableSet<Point2D> path = Sets.mutable.empty();

    private Player getPlayer(HiddenPlayer hiddenPlayer) {
        Player player = players.get(hiddenPlayer);
        if (player == null) {
            player = new Player(hiddenPlayer);
            players.put(player.hiddenPlayer, player);
            enemies.put(player.hiddenPlayer, player);
        }
        return player;
    }

    private Direction moveToOwned() {
        MutableSet<Point2D> targets = me.owned.difference(me.pos);
        if (targets.isEmpty()) {
            return moveTo(myPos);
        } else {
            return moveTo(targets.minBy(myPos::cartesianDistance));
        }
    }

    private Direction moveTo(Point2D target) {
        return DIRECTIONS.minBy(d -> {
            Point2D p = myPos.move(d.vector.getX(), d.vector.getY());
            return !board.inBounds(p) || me.claimed.contains(p) ? Integer.MAX_VALUE : target.cartesianDistance(p);
        });
    }

    @Override
    protected Direction makeMove(ReadOnlyGame readOnlyGame, ReadOnlyBoard readOnlyBoard) {
        board.update(readOnlyBoard);
        myPos = readOnlyBoard.getPosition(this);
        path.remove(myPos);

        for (Player e : players.valuesView()) {
            e.nextMove();
        }
        for (Point2D point : board.allPoints) {
            ReadOnlySplixPoint splixPoint = board.getSplixPoint(point);
            getPlayer(splixPoint.getOwner()).addOwned(point);
            getPlayer(splixPoint.getClaimer()).addClaimed(point);
            getPlayer(splixPoint.getWhosOnSpot()).setPos(point);
        }
        for (Player e : players.valuesView()) {
            e.calcPos();
        }

        if (me.owned.contains(myPos) && path.allSatisfy(p -> me.owned.contains(p))) {
            path.clear();
        }

        if (path.isEmpty()) {
            MutableSet<Point2D> enemyPositions = enemies.valuesView().flatCollect(e -> e.pos).toSet();
            int enemyDistance = enemyPositions.isEmpty() ? Integer.MAX_VALUE :
                    enemyPositions.minBy(myPos::cartesianDistance).cartesianDistance(myPos);

            if (enemyDistance < 20) {
                MutableSet<Point2D> enemyClaimed = enemies.valuesView().flatCollect(e -> e.claimed).toSet();
                if (!enemyClaimed.isEmpty()) {
                    Point2D closestClaimed = enemyClaimed.minBy(myPos::cartesianDistance);
                    if (closestClaimed.cartesianDistance(myPos) < enemyDistance) {
                        return moveTo(closestClaimed);
                    } else if (enemyDistance < 10) {
                        return moveToOwned();
                    }
                }
            }

            if (me.owned.contains(myPos)) {
                if (!me.getUnowned().isEmpty()) {
                    Point2D target = me.getUnowned().minBy(myPos::cartesianDistance);
                    if (target.cartesianDistance(myPos) > 2) {
                        return moveTo(target);
                    }
                }

                int safeSize = Math.max(1, Math.min(enemyDistance / 6, readOnlyGame.getRemainingIterations() / 4));
                SquareRegion region = Lists.mutable
                        .of(new SquareRegion(myPos, myPos.move(safeSize, safeSize)),
                                new SquareRegion(myPos, myPos.move(safeSize, -safeSize)),
                                new SquareRegion(myPos, myPos.move(-safeSize, safeSize)),
                                new SquareRegion(myPos, myPos.move(-safeSize, -safeSize)))
                        .maxBy(r -> me.getUnowned().count(p -> r.inBounds(p)));
                path = board.getBorders(region);
            } else {
                return moveToOwned();
            }
        }

        if (!path.isEmpty()) {
            return moveTo(path.minBy(myPos::cartesianDistance));
        }

        return moveToOwned();
    }
}

```
> 3 votes

# Answer
# TrapBot, Java

```
TrapBot.java

import com.jatkin.splixkoth.ppcg.game.Direction;
import com.jatkin.splixkoth.ppcg.game.SplixPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyBoard;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyGame;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlySplixPoint;
import com.nmerrill.kothcomm.game.maps.Point2D;
import com.nmerrill.kothcomm.game.maps.graphmaps.bounds.point2D.SquareRegion;
import javafx.util.Pair;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.impl.factory.Lists;

import java.util.Comparator;

/**
 * Trap bot goes to the wall and traces the entirety around. Hopes that
 * the players in the middle die and that nobody challenges him. Nearly
 * all turns are left turns.
 */
public class TrapBot extends SplixPlayer {

    /**
     * Mode when the bot is attempting to reach the wall from it's original spawn
     * location.
     */
    public static final int MODE_GOING_TO_WALL = 1;

    /**
     * Mode when we have reached the wall and are now going around the board.
     */
    public static final int MODE_FOLLOWING_WALL = 2;

    private int mode = MODE_GOING_TO_WALL;

    public static int WALL_EAST = 1;
    public static int WALL_NORTH = 2;
    public static int WALL_WEST = 3;
    public static int WALL_SOUTH = 4;

    /**
     * How long the bot would like to go before he turns around to go back home.
     */
    private static final int PREFERRED_LINE_DIST = 5;

    private int distToTravel = 0;

    private Direction lastMove = Direction.East;// could be anything that's not null
    private int lastTrailLength = 0;

    @Override
    protected Direction makeMove(ReadOnlyGame game, ReadOnlyBoard board) {
        Direction ret = null;
        MutableMap<Point2D, ReadOnlySplixPoint> view = board.getView();
        int trailLength = getTrailLength(board, view);

        if (trailLength == 0) {

            int closestWall = getClosestWall(board);
            Direction directionToWall = getDirectionToWall(closestWall);

            if (lastTrailLength != 0) {
                ret = lastMove.leftTurn();
                // move to the other half of 2 width line so we can start without shifting to the left
            }

            if (mode == MODE_GOING_TO_WALL && ret == null) {
                int distCanTravel = getDistCanTravel(
                        getSelfPosition(board), board.getBounds(), directionToWall);
                if (distCanTravel == 0) mode = MODE_FOLLOWING_WALL;
                else ret = directionToWall;
                distToTravel = distCanTravel;

            }

            if (mode == MODE_FOLLOWING_WALL && ret == null) {
                int distCanTravel = 0;
                ret = directionToWall;
                while (distCanTravel == 0) {// keep turning left until we can get somewhere
                    ret = ret.leftTurn();
                    distCanTravel = getDistCanTravel(
                            getSelfPosition(board), board.getBounds(), ret);
                }

                distToTravel = distCanTravel;
            }
        }

        // once we have started we are on auto pilot (can't run after the before block)
        else if (trailLength == distToTravel || trailLength == (distToTravel + 1))
            ret = lastMove.leftTurn();

        if (ret == null)// if we don't have a move otherwise, we must be on our trail. ret same as last time
            ret = lastMove;

        lastTrailLength = trailLength;
        lastMove = ret;
        return ret;
    }

    int getClosestWall(ReadOnlyBoard board) {
        Point2D thisPos = getSelfPosition(board);
        return Lists.mutable.of(
                new Pair<>(WALL_NORTH, board.getBounds().getTop() - thisPos.getY()),
                new Pair<>(WALL_SOUTH, thisPos.getY()),
                new Pair<>(WALL_EAST, board.getBounds().getRight() - thisPos.getX()),
                new Pair<>(WALL_WEST, thisPos.getX())
        ).min(Comparator.comparingInt(Pair::getValue)).getKey();
    }

    /**
     * This goes around some intended behavior in the controller to get the correct result. When a player goes outside
     * his territory the land under him is converted to a trail -- on the next step of the game. So a trail length may
     * be the count of the trail locations plus one. That is what this function calculates. Depends on the whole trail
     * being contained inside the view passed to it.
     * @return
     */
    int getTrailLength(ReadOnlyBoard board, MutableMap<Point2D, ReadOnlySplixPoint> view) {
        boolean isPlayerOutsideHome = !view.get(getSelfPosition(board)).getOwner().equals(getThisHidden());
        int trailLength = view.count(rop -> rop.getClaimer().equals(getThisHidden()));
        return trailLength + (isPlayerOutsideHome? 1 : 0);
    }

    /**
     * Calculate how far we can travel in the direction before we hit the wall.
     * @return
     */
    int getDistCanTravel(Point2D currPos, SquareRegion bounds, Direction direction) {
        for (int i = 1; i <= PREFERRED_LINE_DIST; i++) {
            if (!bounds.inBounds(currPos.move(direction.vector.getX()*i, direction.vector.getY()*i)))
                return i-1;
        }
        return PREFERRED_LINE_DIST;
    }

    /**
     * Get which direction needs to be traveled to reach the specified wall.
     * Requires that neither Direction nor the values of `WALL_...` change.
     * @param targetWall
     * @return
     */
    Direction getDirectionToWall(int targetWall) {
        return Direction.values()[targetWall-1];
    }
}

```

This is perhaps the most simple bot. All it does is trace out the edge of the board, doubling back on itself to reduce risk of being killed.
> 1 votes

# Answer
# random\_bot, Clojure

This is **RandomBot**, but I had to stick to naming conventions, and some issues prevent me from using the hyphen in the name, so underscores reign! The `make-move` fn returns a vec with the first item being the `Direction` you want to move in, and the second being the state you want to be passed back to you on the next turn. Do not use any external atoms, since this code may be running multiple games in parallel.

```
 random_bot.clj
 (ns random-bot
     (:import
      [com.jatkin.splixkoth.ppcg.game Direction]))

 (defn make-move [game board state]
       [(rand-nth [Direction/East
                   Direction/West
                   Direction/North
                   Direction/South])
        nil])

```
> 1 votes

# Answer
# HunterBot, Java

```
HunterBot.java

import com.jatkin.splixkoth.ppcg.game.Direction;
import com.jatkin.splixkoth.ppcg.game.SplixPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.HiddenPlayer;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyBoard;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlyGame;
import com.jatkin.splixkoth.ppcg.game.readonly.ReadOnlySplixPoint;
import com.nmerrill.kothcomm.game.maps.Point2D;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.api.set.ImmutableSet;
import org.eclipse.collections.impl.factory.Sets;

import java.util.Comparator;

/**
 * This bot looks for any trail points left behind by another player and sets that as his target. If the target ever
 * disappears, it will continue on in hopes that the player will return soon, or if another target appears, it will
 * go towards that one. Works best when the other player repeatedly goes in the same general direction.
 */
public class HunterBot extends SplixPlayer {

    private Point2D lastTarget;

    private Direction lastMove = Direction.East;

    @Override
    protected Direction makeMove(ReadOnlyGame game, ReadOnlyBoard board) {
        Point2D thisPos = getSelfPosition(board);
        MutableMap<Point2D, ReadOnlySplixPoint> global = board.getGlobal();
        MutableMap<Point2D, ReadOnlySplixPoint> targets = global.select((pt, rosp) ->
                !rosp.getClaimer().equals(getThisHidden())
                        && !rosp.getClaimer().equals(new HiddenPlayer(null)));

        if (targets.size() == 0 && lastTarget == null) {
            lastMove = lastMove.leftTurn();
            return lastMove;
        }

        Point2D target = null;
        if (targets.size() == 0) target = lastTarget;
        else target = targets.keysView().min(Comparator.comparingInt(thisPos::cartesianDistance));
        if (target.equals(thisPos)) {
            lastTarget = null;
            if (global.get(thisPos).getOwner().equals(getThisHidden())) {
                lastMove = lastMove.leftTurn();
                return lastMove;
            } else
            // time to go home
            target = global.select((z_, x) -> getThisHidden().equals(x.getOwner())).keySet().iterator().next();

        }

        lastTarget = target;
        lastMove = makeSafeMove(target, global, board, thisPos);
        return lastMove;
    }

    private Direction makeSafeMove(Point2D targetLocation, MutableMap<Point2D, ReadOnlySplixPoint> map, ReadOnlyBoard board, Point2D currLoc) {
        Point2D dist = targetLocation.move(-currLoc.getX(), -currLoc.getY());
        ImmutableSet<Direction> possibleMoves = Sets.immutable.of(Direction.values())
                .select(x -> {
                    Point2D pos = currLoc.move(x.vector.getX(), x.vector.getY());
                    return !board.getBounds().outOfBounds(pos) && !getThisHidden().equals(map.get(pos).getClaimer());
                });
        Direction prefMove;
        if (Math.abs(dist.getX()) > Math.abs(dist.getY()))
            prefMove = getDirectionFroPoint(new Point2D(normalizeNum(dist.getX()), 0));
        else
            prefMove = getDirectionFroPoint(new Point2D(0, normalizeNum(dist.getY())));

        if (possibleMoves.contains(prefMove)) return prefMove;
        if (possibleMoves.contains(prefMove.leftTurn())) return prefMove.leftTurn();
        if (possibleMoves.contains(prefMove.rightTurn())) return prefMove.rightTurn();
        return prefMove.leftTurn().leftTurn();
    }

    private Direction getDirectionFroPoint(Point2D dir) {
        return Sets.immutable.of(Direction.values()).select(d -> d.vector.equals(dir)).getOnly();
    }

    private int normalizeNum(int n) { if (n < -1) return -1; if (n > 1) return 1; else return n;}

}

```

One of the most basic bots. It searches the board for spots to kill others, and it will follow the shortest path possible to get to a killing position. If it is outside its territory, it will make random moves until it has another opening to kill another player. It has some logic to prevent it fomr running over itself, and when all other players are dead it goes back to its home. Once home it just goes in a little square.
> 0 votes

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


title: Draw an ASCII cuboid

text:
# Question
Title: Draw an ASCII cuboid
Given three integers \>= 2, create an ASCII cube in an orthogonal (cabinet) projection. The three integers represent height, width and depth (measured in visible characters) including the corners. The corners should be 'o's or '+', free choice.

w: 10, h: 5, d: 4 Thus gives:

```
   o--------o
  /        /|
 /        / |
o--------o  |
|        |  o
|        | /
|        |/
o--------o

```

Now, to make this slightly harder, all faces can either be solid, transparent or missing. We order the faces like this:

```
   o--------o
  /        /|
 /    2   / |
o--------o 3|
|        |  o
|   1    | /
|        |/
o--------o

  ---
  |2|
-------
|5|1|3|
-------
  |4|
  ---
  |6|
  ---

```

And supply a list of tokens, S, T or M. The original example is thus:

```
w 10
h 5
d 4
S S S S S S

   o--------o
  /        /|
 /        / |
o--------o  |
|        |  o
|        | /
|        |/
o--------o

```

If one face is transparent, we can see anything that is behind it:

```
T S S S S S

   o--------o
  /        /|
 /        / |
o--------o  |
|  o-----|  o
| /      | /
|/       |/
o--------o

T T T T T T

   o--------o
  /|       /|
 / |      / |
o--------o  |
|  o-----|--o
| /      | /
|/       |/
o--------o

```

For pairs of missing faces, adjacent edges or corners are no longer visible:

```
M M S S S S

   o--------o
  /|       /|
 / |      / |
o  |     o  |
|  o-----|  o
| /      | /
|/       |/
o--------o

M M S S M S

   o--------o
   |       /|
   |      / |
   |     o  |
   o-----|  o
  /      | /
 /       |/
o--------o

```

Code golf, shortest code wins! Trailing spaces and newlines are fine, you're free to choose input method and input order.

# Answer
# Charcoal, ~~190~~ 181 bytes

```
ＮωＡ⁻ω²ςＮηＡ⁻η²γＮδＡ⁻δ²χＡ⪪Ｓ αＦ›⊟αMＦ⟦ςγςγ⟧«oκ↶»Ｆ∧›⊟αM²«oς↷³oχ↷¹»Ｆ∧›⊟αM²«↷³oχ↷³oγ↶»Ｍ⁻ωδ⁻δηＦ⁼§α²SＧ↗δ↓η↙δ↑η Ｆ∧›⊟αM²«↶¹oχ↷³oγ↷»Ｆ⁼§α¹SＧ↗δ←ω↙δ→ω Ｆ∧›⊟αM²«↶¹oχ↶³oς»Ｆ⁼§α⁰SＵＯ±ωη ↷Ｆ›⊟αMＦ⟦γςγς⟧«oκ↷

```

Try it online! Link is to verbose version of code. Edit: Saved 9 bytes by optimising my conditions. Charcoal has no `else` token, so `if` commands always have two alternatives, unless they're at the end of a block or program. To avoid this, I use `for (<bool>)` instead of `if (<bool>)` which has a similar effect when the expression can only have the values 0 or 1 but saves a byte. (In order to achieve this I had to change the expressions so that they were always true when the body needed to be executed.) I was also able to optimise `if (<bool>) for (<int>)` into `for (And(bool, int))`.
> 5 votes

# Answer
## JavaScript (ES6), ~~318~~ ~~314~~ 308 bytes

Takes width, height and depth as integers and the faces as an array of characters.

```
(w,h,d,l,M=(n,F)=>[...Array(n+1).keys()].map(F),a=M((L=w--+d)*(h--+--d),i=>++i%L?' ':`
`),D=(t,Y=0,X=d,W=t&1?d:w,H=t&2?d:h,F=l[t>>2])=>F>'R'&&M(W,i=>M(H,j=>a[p=L*(Y+j-i*(t&1))+X+i-(t&2?j:0)]=(x=!(i&&i-W)|2*!(j&&j-H))?' |-o|/o/-o'[t%4*3+x]:a[F>'S'?p:0])))=>D(20)&D(D(14,h)&D(17,d,0),d,D(9,d,w)&D(6))||a.join``

```

### How?

The function ***M()*** processes a given callback ***F*** on a given range ***\[0...n\]***.

```
M = (n, F) => [...Array(n + 1).keys()].map(F)

```

The variable ***a*** holds a flat array representing a grid of size ***(w+d) x (h+d-1)***. It is initially filled with rows of spaces terminated with newlines.

```
a = M((L = w-- + d) * (h-- + --d), i => ++i % L ? ' ' : '\n')

```

The function ***D()*** is used to 'draw' a face of the cuboid.

The two least significant bits of the parameter ***t*** hold the face type:

* 0 = rear / front
* 1 = left / right
* 2 = bottom / top

Bits #2 to #4 hold the 0-based face index.

```
D = (                                           // given:
  t, Y = 0, X = d,                              // - the type and the initial coordinates
  W = t & 1 ? d : w,                            // - the drawing width
  H = t & 2 ? d : h,                            // - the drawing height
  F = l[t >> 2]                                 // - the character representing the status
) =>                                            //
  F > 'R' &&                                    // provided that the face is not missing:
  M(W, i =>                                     // for each i in [0...W]:
    M(H, j =>                                   //  for each j in [0...H]:
      a[                                        //    update the output
        p = L * (Y + j - i * (t & 1)) +         //    at position p
            X + i - (t & 2 ? j : 0)             //
      ] =                                       //    with either:
      (x = !(i && i - W) | 2 * !(j && j - H)) ? //    - '|', '-' or '/' on edges
        ' |-o|/o/-o'[t % 4 * 3 + x]             //    - or 'o' on vertices
      :                                         //
        a[F > 'S' ? p : 0]                      //    - or a space on solid faces
    )                                           //    - or the current character on
  )                                             //      transparent faces

```

Faces are drawn in the following order:

```
D(5 * 4 + 0, 0, d)  // face #5 (rear)
D(3 * 4 + 2, h, d)  // face #3 (bottom)
D(4 * 4 + 1, d, 0)  // face #4 (left)
D(2 * 4 + 1, d, w)  // face #2 (right)
D(1 * 4 + 2, 0, d)  // face #1 (top)
D(0 * 4 + 0, d, 0)  // face #0 (front)

```

### Demo

```
let f =

(w,h,d,l,M=(n,F)=>[...Array(n+1).keys()].map(F),a=M((L=w--+d)*(h--+--d),i=>++i%L?' ':`
`),D=(t,Y=0,X=d,W=t&1?d:w,H=t&2?d:h,F=l[t>>2])=>F>'R'&&M(W,i=>M(H,j=>a[p=L*(Y+j-i*(t&1))+X+i-(t&2?j:0)]=(x=!(i&&i-W)|2*!(j&&j-H))?' |-o|/o/-o'[t%4*3+x]:a[F>'S'?p:0])))=>D(20)&D(D(14,h)&D(17,d,0),d,D(9,d,w)&D(6))||a.join``

let update = _ => O.innerHTML = f(W.value, H.value, D.value, [...F.value])
update()
```

```
<label>Width <input id="W" size="3" value="10" oninput="update()" /></label>
<label>Height <input id="H" size="3" value="5" oninput="update()" /></label>
<label>Depth <input id="D" size="3" value="4" oninput="update()" /></label>
<label>Faces <input id="F" size="6" value="MMSSMS" oninput="update()" /></label>
<pre id="O"></pre>
```
> 2 votes

# Answer
# SOGL V0.11, ~~200~~ ~~194~~ ~~193~~ ~~192~~ 190 bytes

```
b³@*⁶
ž}1}X⁵
;aκ⁴
2-³
* o1Ο²
d=?a³:?∫:¹
be.Aā6∫D,ζLI%:C?abe"DCa∫:c+H⁴d+ /ž}{"a+Hy"e³┐²čž|"b³┌²žz"EBAøp”,ōkB°s9θW=*↑(⅜⅞~υ=\⁰ōwūΧ►ΣΤP░¶Ο⁽◄Φ7⅟▲s#‘┌Θdwι+#¶ŗ!!6c=?6d=?2aI⁶e³∙ž}5¹b+⁴Ie³@∙⁵}4¹2+⁴⁶⁵

```

Takes input in the order

```
width
height
depth
down-face
left-face
back-face
top-face
right-face
front-face

```

Tied!
Try it Here! (compressed value changed to be V0.12 compatible)
> 1 votes

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