title: Pi == 3.2

text:
# Question
Title: Pi == 3.2
Inspired by this video of *Infinite Series*.

### Introduction

Pi is defined as the ratio of the circumference to the diameter of a circle. But how is a circle defined? Usually a circle is defined as the points with constant distance to the centerpoint (let us assume that the center is at `(0,0)`). The next question would be: How do we define the *distance*? In the following we are considering different notions of distances (induced by the `Lp`-norms):

Given a norm (=something that measures a *length*) we can easily construct a *distance* (=distance between two points) as follows:

```
dist(A,B) := norm (A-B)

```

The euclidean norm is given by:

```
norm((x,y)) = (x^2 + y^2)^(1/2)

```

This is also called the *L2-norm*. The other *Lp-norms* are constructed by replacing the `2` in the above formula by other values between 1 and infinity:

```
norm_p((x,y)) = (|x|^p + |y|^p)^(1/p)

```

The unit circles for those different norms have quite distinct shapes:

### Challenge

Given a `p >= 1`, calculate the ratio of circumference to diameter of a *Lp-circle* with respect to the `Lp`-norm with an accuracy of four significant figures.

### Testcases

We can use that for `p,q` with `1 = 1/p + 1/q` we get the same ratio for the `Lp` as well as the `Lq` norm. Furthermore for `p = q = 2` the ratio is minimal, and for `p = 1, q = infinity` we get a ratio of 4, so the ratios are always between `pi` and `4`.

```
p   or  q            ratio
1       infinity     4
2       2            3.141592
1.623   2.60513      3.200
1.5     3            3.25976
4       1.33333      3.39693

```

# Answer
> 14 votes
# Python + scipy, 92 bytes

```
from scipy.integrate import*
lambda p:2/p*quad(lambda x:(x/x**p+(1-x)**(1-p))**(1/p),0,1)[0]

```

Formula is from this math.SE question.

# Answer
> 11 votes
# MATL, 31 bytes

```
0:1e-3:1lyG^-lG/^v!d|G^!slG/^sE

```

Try it online! Or verify all test cases.

### Explanation

This generates the *x*,*y* coordinates of one quarter of the unit circle sampled at 1001 points with step 0.001 in *x*. The length of the quarter of circle is approximated by that of the polygonal line that passes through those points; that is, the sum of the lengths of the 1000 segments. Length is of course computed according to `p`-norm. Multiplying the result by 2 gives the approximate lenght of half a circle, that is, pi.

```
0:1e-3:1   % Push [0 0.001 0.002 ... 0.999 1]. These are the x coordinates of
           % the vertices of the polygonal line that will approximate a quarter
           % of the unit circle
l          % Push 1
y          % Duplicate [0 0.001 0.002 ... 0.999 1] onto the top of the stack.
G          % Push input, p
^          % Element-wise power: gives [0^p 0.001^p ... 1^p]
-          % Element-wise subtract from 1: gives [1-0^p 1-0.001^p ... 1-1^p]
lG/        % Push 1, push p, divide: gives 1/p
^          % Element-wise power: gives [(1-0^p)^(1/p) (1-0.001^p)^(1/p) ...
           % ... (1-1^p)^(1/p)]. These are the y coordinates of the vertices
           % of the polygonal line
v          % Concatenate vertically into a 2×1001 matrix. The first row contains
           % the x coordinates and the second row contains the y coordinates
!          % Transpose
d|         % Compute consecutive differences down each column. This gives a
           % 1000×2 matrix with the x and y increments of each segment. These
           % increments will be referred to as Δx, Δy
G          % Push p
^          % Element-wise power
!          % Transpose
s          % Sum of each column. This gives a 1×1000 vector containing
           % (Δx)^p+(Δy)^p for each segment
lG/        % Push 1/p
^          % Element-wise power. This gives a 1×1000 vector containing
           % ((Δx)^p+(Δy)^p)^(1/p) for each segment, that is, the length of
           % each segment according to p-norm
s          % Sum the lenghts of all segments. This approximates the length of
           % a quarter of the unit circle
E          % Multiply by 2. This gives the length of half unit circle, that is,
           % pi. Implicitly display

```

# Answer
> 10 votes
# Wolfram Language (Mathematica), ~~49~~ ~~46~~ 45 bytes

*3 bytes saved thanks to alephalpha.*
*1 byte saved thanks to att.*

```
\!\(2N@∫\_0\%1\@+++(a^-#-1)^(1-#)\%#a\)&

```

Try it online! Pure function. Takes a number as input and returns a number as output. The Unicode characters are U+222B for `\[Integral]` and U+F74C for `\[DifferentialD]`.

# Answer
> 6 votes
## PARI/GP, ~~48~~ 43 bytes

It's easy after @orlp has found the formula, and @alephalpha's version saves 5 bytes:

```
p->2*intnum(u=0,1,(1+(u^-p-1)^(1-p))^(1/p))

```

To add something slightly useful, let's calculate the `p` for which we get `3.2`:

```
? f=p->2*intnum(u=0,1,(1+(u^-p-1)^(1-p))^(1/p));
? solve(p=1,2,f(p)-3.2)
%2 = 1.623002382384469009676324702

```

### Correct usage

While the code gives results that are much more exact than the challenge demands, it can easily be improved a lot: if we replace the upper integration limit `1` with `[1,1/p-1]` (giving what the manual calls the singularity exponent) then all shown digits of `f(2)` agree with `Pi`. This is still true if we increase the precision to 100 (type `\p100`).

However, after that change the `solve` computation no longer worked. I changed the inner term to explicitely handle the case `u=0` and also changed to a different computer with a newer PARI version and 64 bit (which implies a higher default precision).

Here is the improved calculation of the `p` value for `Pi=3.2`, and let's also have a look at the real Pi:

```
? f=p->2*intnum(u=0,[1,1/p-1],if(u,(1+(u^-p-1)^(1-p))^(1/p),0));
? f(2)
%2 = 3.1415926535897932384626433832795028842
? Pi
%3 = 3.1415926535897932384626433832795028842
? solve(p=1,2,f(p)-3.2)
%4 = 1.6230023823844690096763253745604419761

```

# Answer
> 4 votes
# Desmos, 42 bytes

```
f(p)=2∫_0^1(x/x^p+(1-x)^{1-p})^{1/p}dx/p

```

Port of orlp's integration formula. Yay for integration built-in!

Try it on Desmos!

# Answer
> 2 votes
## JavaScript (ES7), 80 bytes

Based on orlp's answer. This JS implementation is quite slow. You may want to try `i=1e-7` (or even higher) for a faster approximation.

*Note*: This is basically intended for Chrome and Edge only. An equivalent ES6 version using `Math.pow()` on Firefox 50.1 seems to be *much* slower.

*Edit*: According to Neil, this should also work fine on Firefox 52.

```
f=
p=>{for(i=5e-8,s=x=0;(x+=i)<1;)s+=i*(x**(1-p)+(1-x)**(1-p))**(1/p);return 2/p*s}

console.log(f(1).toFixed(3))
console.log(f(2).toFixed(3))
console.log(f(1.623).toFixed(3))
```

---
Tags: code-golf, math, geometry, calculus
---


title: King of The Holster (finished)

text:
# Question
Title: King of The Holster (finished)
## CLOSED to competing entries

New bots are welcome but are not part of the main competition and probably won't be officially tested.

You stand on a dusty stretch of code, watching the other programs stare at you. Will they shoot? How much ammunition do they have left? All you know is that you want to be the last one standing.

## Before the Game

You will be given 10 points to distribute between HP, Dexterity, Armor, and Speed. You may distribute up to 10 points between these categories (integer amounts only). You may put 0 points into a category.

* Your HP will equal 10 plus the number of points you put in HP.
* Your Dexterity (chance of dodging a hit) is equal to 0.04 times the number of points you put in Dexterity. For example, if you put 8 points in Dex, you would have a .32 chance of dodging a hit.
* Your Armor (chance of taking 1 less damage from a hit) is equal to .1 times the number of points you put into Armor.
* Your Speed is simply equal to the number of points you put in Speed.
* You always start with 2 ammo.

## Gameplay

This game is turn-based. Agents will be ordered based on their speed, with ties being broken at random before the game begins. Each agent will take their turn, choosing one of the three move options and executing it, then the next player will go. Unlike many KoTHs similar to this one, moves are NOT all executed at the same time.

On each agent's turn, there are three possible moves:

* Heal: If not at maximum HP, gain 1 HP.
* Reload: Gain 2 ammo.
* Shoot: Choose another agent. That agent rolls for dexterity (creates a random real, and wins the roll if their dexterity is higher). If they win the roll they dodge and take 0 damage. Otherwise, they roll for armor. If they win, they take a random amount of damage from 0 to 3, while if they lose, they take a random amount of damage from 1 to 4. All damage is integers.

Once an agent's HP is less than 0, it is out and can no longer take actions. Last agent surviving wins the round.

## Scoring

Each round, if there were X agents, your agent receives X points for each agent below it, plus an extra 2 points if they win. Therefore, in a 10 player game, the top agent would get 11 points, the second would get 8, and so on. As long as all the agents run fast, I should be able to run thousands (maybe hundreds of thousands) of tests, so the scores should be well-distributed. All scores are divided by the number of rounds played for ease of use.

## I/O

All players will create a class which extends PlayerClass. As an example, you can look at any of the four (non-competing) bots created in the github. Each bot will have a class constructor which initializes the stats picked earlier and a `makeMove()` function, which determines what action to take and who is the target. For input, you have access to the following functions:

1. getHP() (gets current HP)
2. getAmmo() (gets ammo amount)
3. getMaxHP() (gets your max HP)
4. getDex() (gets dexterity)
5. getArmor() (gets armor)
6. getSpeed() (gets speed, you MAY call this on other players)
7. getPlayers() (gets list of all players)
8. getShotAt() (gets the PlayerClass object who you shot at most recently)
9. getShotBy() (gets the PlayerClass object who shot at you most recently)
10. getAliveEnemies() (gets a list of all players who have 1 or more HP and are not you)
11. deadQ() (gets whether a player is dead, you MAY call this on other players)
12. compareTo(PlayerClass p) (gets p's speed minus your speed)
13. getWhoShotYou()(gets all bots who shot you (in a random order) since the last time you called the move() action)

The lists of players (getPlayers and getAliveEnemies) should be in turn order, so that allows you to check who will shoot next and/or solve ties in speed.

## Rules for Bounty

If, at the end of the challenge (May 6, 20:00 GMT), the current winning bot is in the lead by at least 1 point AND in no way targets specific bots/acts differently based on the bots it faces, that bot will be given the bounty.

Otherwise, if a bot posted after the bounty satisfied this condition at one point, the most recent bot to do so will receive the bounty.

If no bot ever managed to meet the required conditions, the bounty will be awarded to the winner of the KoTH.

You may NOT delete bots you submitted previously to make your bot perform better. If you will delete a bot, I recommend deleting one of your worst ones.

As an example, Destroyer would currently meet the no-targeting requirement (since it simply shoots the first bot in the turn order), but only is leading by around .6 points, so doesn't meet the point requirement.

## Rules

Submissions in Java only. As long as the submission is simple enough, I might be able to translate from pseudocode/some other language to Java though.

You may only enter 5 bots at any one time, and your bots may not collaborate. Feel free to submit more than 5, but when you submit a new one, set another one as noncompeting.

You MAY design your bots to target specific bots and/or predict what they will do, as long as it doesn't massively help your other bots.

No calling any methods of other entities, except for the ones called out above. The biggest problem here is `takeDamage()`, which has to be public so it can be called when someone is shot.

No redefining any functions/variables of PlayerClass besides `makeMove()`.

The subclass constructor must be of the form `super(x,y,z,a);` and cannot overwrite the requirements in the PlayerClass constructor (for example, allowing yourself to spend more than 10 points).

Feel free to define other methods of your class and/or create variables for memory purposes. Between each game, your bot will be reset, so it will only affect each individual game.

Don't make your code take forever. This KOTH is pretty lightweight, so there shouldn't be a need for complex algorithms.

---

## Leaderboard (FINAL STANDINGS)

```
ChargeBot->0.10870789129210871

SmartBot->1.151028848971151

Tank->3.4236785763214237

RageBot3->3.693295306704693

OneVsOneMeBro->3.7322532677467324

FriendlyAndHealthyBot->5.668694331305669

HpKing->7.525759474240526

FriendlyNotFriendlyBot->7.694217305782694

WinnerBot->8.004405995594004

NormalBot->8.276454723545276

Destroyer->8.732566267433732

StrategicBot->8.91998708001292

Dexter->9.556512443487556

WhatABot->10.622109377890622

FocusFireBot->10.945748054251945

```

---

FocusFireBot takes the victory!

---

The controller and all current agents can be found here: https://github.com/romanpwolfram/GunfightKoTH/tree/main

Challenge name by tjjfvi.

# Answer
> 2 votes
# FocusFireBot

```
package standoffKOTH;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class FocusFireBot extends PlayerClass {
    private PlayerClass focusTarget;
    private Map<PlayerClass, Integer> targetedBy = new HashMap<PlayerClass, Integer>();
    private List<PlayerClass> targetedLastRound = new ArrayList<PlayerClass>();
    protected int move = 0;
    private int movesPerRound = 250;

    public FocusFireBot() {
        super(0, 0, 10, 0);
    }

    protected int makeMove() {
        move++;
        if (deadQ()) {
            return 0;
        }
        // fully heal
        if (getHP() < getMaxHP()) {
            return this.move('h', this);
        }
        if (focusTarget != null && focusTarget.deadQ()) {
            focusTarget = null;
        }

        // if we have a target we kill or we die
        if (focusTarget != null) {
            if (getAmmo() < 1) {
                return this.move('r', this);
            } else {
                return this.move('s', focusTarget);
            }
        }

        List<PlayerClass> aliveEnemies = getAliveEnemies();
        // if only one enemy is left target it
        if (aliveEnemies.size() < 2) {
            focusTarget = aliveEnemies.get(0);
        } else {
            // if someone shot us twice in a row, we set him as target
            // if (getShotBy() != null && !getShotBy().deadQ()) {
            // focusTarget = getShotBy();
            // }
            List<PlayerClass> targetedThisRound = getWhoShotYou();
            for (PlayerClass player : targetedThisRound) {
                if (!player.deadQ()) {
                    if (targetedLastRound.contains(player)) {
                        focusTarget = player;
                    }
                    targetedBy.merge(player, 1, Integer::sum);
                } else {
                    targetedLastRound.remove(player);
                }
            }
        }
        // shoot if we where shot twice in a row
        if (focusTarget != null) {
            if (getAmmo() < 1) {
                return this.move('r', this);
            } else {
                return this.move('s', focusTarget);
            }
        }

        // fully heal
        if (getHP() < getMaxHP()) {
            return this.move('h', this);
        }
        // get enought ammo to sustain focused fire
        if (getAmmo() < 50 && getAmmo() + move < movesPerRound) {
            return this.move('r', this);
        }

        // focus on player who shot us the most
        List<Entry<PlayerClass, Integer>> shotByList = new ArrayList<>(targetedBy.entrySet());
        shotByList.sort(Entry.comparingByValue());
        Collections.reverse(shotByList);
        for (Entry<PlayerClass, Integer> playerE : shotByList) {
            PlayerClass player = playerE.getKey();
            if (player.deadQ()) {
                targetedBy.remove(player);
            } else {
                focusTarget = player;
                return this.move('s', focusTarget);
            }
        }

        //
        focusTarget = aliveEnemies.get(0);
        return this.move('s', focusTarget);
    }
}

```

If you get his attention there are only two possible outcomes: **You or he dies!**

### Update 1

* added move counter and made reload condition so that it does not reload if it has enough ammo for shooting until end --\> reduces ties but overall little impact and requires knowlege of turns per round
* went full armor and health is now most important (even more than shooting) --\> more score but also more ties

### Last Udate

* now picking of fastest bot than slowest

# Answer
> 6 votes
# #1 - FriendlyNotFriendlyBot

```
package standoffKOTH;

import java.util.Random;

public class FriendlyNotFriendlyBot extends PlayerClass
{
    Random rand = new Random();

    public FriendlyNotFriendlyBot()
    {
        super(10, 0, 0, 0);
    }

    @Override
    protected int makeMove()
    {
        if (this.getAmmo() < 1)
            return this.move('r', this);
        else if (this.getShotBy() != null && !this.getShotBy().deadQ())
            return this.move('s', this.getShotBy());
        else if (this.getAmmo() < 10)
            return this.move('r', this);
        else if (this.getHP() < 20)
            return this.move('h', this);
        else
            return this.move('s', this.getAliveEnemies().get(rand.nextInt(this.getAliveEnemies().size())));
    }
}

```

This bot tests these conditions, in order:

* If it has no ammo, it refills.
* If it is getting attacked, and the opponent is still alive, it will retaliate.
* If it has less than 10 ammo, it refills.
* If it has less than 20 health, it heals.
* Else, it shoots at random.

**There is a flaw**: if it got attacked twice or more in the same turn, but the last attacker is dead, it will not retaliate because only the last attacker can be viewed.

*Trivia*: There is an interesting Prisoner's dilemma with the Speed of the bots. The thing is the most effective strategy is to have the speed to 0, but if someone increases his speed to 1, he will be faster and therefore win. But in this case, others will increase their speed to 2, and progressively to the maximum 10. At this point however, a player can set his speed back to 0 and win easily.

# #2 - FriendlyAndHealthyBot

```
package standoffKOTH;

import java.util.Random;

public class FriendlyAndHealthyBot extends PlayerClass
{
    Random rand = new Random();

    public FriendlyNotFriendlyBot()
    {
        super(10, 0, 0, 0);
    }

    @Override
    protected int makeMove()
    {
        if (this.getAmmo() < 1)
            return this.move('r', this);
        else if (this.getShotBy() != null && !this.getShotBy().deadQ())
            return this.move('s', this.getShotBy());
        else if (this.getHP() < 20)
            return this.move('h', this);
        else
            return this.move('s', this.getAliveEnemies().get(rand.nextInt(this.getAliveEnemies().size())));
    }
}

```

A slight variation of FNFB.

This bot tests these conditions, in order:

* If it has no ammo, it refills.
* If it is getting attacked, and the opponent is still alive, it will retaliate.
* If it has less than 20 health, it heals.
* Else, it shoots at random.

# Answer
> 4 votes
# Example Bots

These bots will not compete, but will likely be included in the test rounds for the first few bots and have a few useful examples.

## Bot 0: ExampleBot

Literally just heals, no stats.

```
package standoffKOTH;

public class ExamplePlayerClass extends PlayerClass {

    public ExamplePlayerClass()
    {
        super(0,0,0,0);//put stats here
    }
    protected int makeMove()
    {
        return this.move('h',this);//It doesn't matter who is target with non-shoot actions, so just self here
    }
}

```

## Bot 1: RevengeBot

Shoots whoever shot it last. Is happy to just reload until it is shot. If whoever shot it is now dead, it goes into a rage and picks someone at random to shoot.

```

package standoffKOTH;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Player1Class extends PlayerClass {

    public Player1Class()
    {
        super(0,8,1,1);
    }
    protected int makeMove()
    {
        List<PlayerClass> g = new ArrayList<PlayerClass>();g= this.getAliveEnemies();
        if((int)getHP()<6)
        {return this.move('h', this);}
        else {
            if (getAmmo()<1)
            {return this.move('r',this);}
            else {
            if(getShotBy()!=null&& g.contains(getShotBy())) {
                if(getAmmo()>0){
                    return this.move('s',(PlayerClass) getShotBy());}
                else{
                    return this.move('r',this);}}
            else{
                if(getShotBy()!=null&&(getShotBy()).deadQ()&&getAliveEnemies().size()!=0)
                {Collections.shuffle(g);return this.move('s',g.get(0));}
                else {return this.move('r', this);}}
    }}}
}

```

## Bot 2: RandomBot

Will pretty much shoot anyone who's still alive, other than itself, of course. It may be random, but it's no EmoWolf.

```
package standoffKOTH;

import java.util.List;
import java.util.Random;

public class Player2Class extends PlayerClass {
    Random rand = new Random();
    public Player2Class()
    {
        super(9,0,0,1);
    }
    protected int makeMove()
    {
        List<PlayerClass> z = getAliveEnemies();
        if(getAmmo()>0) {return this.move('s',z.get(rand.nextInt(z.size())));}{return this.move('r',this);}
    }
}

```

## Bot 3: DedicatedBot

Just like RevengeBot, DedicatedBot won't shoot until shot. However, DedicatedBot will shoot a specific bot until they die, then switch to another random bot. DedicatedBot also won't heal (unless they are already dead, in which case it doesn't matter). It's just that dedicated.

```
package standoffKOTH;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Player3Class extends PlayerClass {
    PlayerClass firstShot = null;
    public Player3Class()
    {
        super(5,0,5,0);
    }
    protected int makeMove()
    {
        List<PlayerClass> g = new ArrayList<PlayerClass>();g= this.getAliveEnemies();
        if(getShotBy()!=null&&firstShot==null) {firstShot = (PlayerClass) getShotBy();}
        if(getHP()<1)
        {return this.move('h', this);}
        else {
            if (getAmmo()<2)
            {return this.move('r',this);}
            else {
            if(firstShot!=null&& g.contains(firstShot)) {
                if(getAmmo()>0){
                    return this.move('s',firstShot);}
                else{
                    return this.move('r',this);}}
            else{
                if(getShotBy()!=null&&((PlayerClass)getShotBy()).deadQ()&&this.getAliveEnemies().size()!=0)
                {Collections.shuffle(g);return this.move('s',g.get(0));}
                else {return this.move('r', this);}}
    }}}
}

```

## Bot 4: PsychopathBot

The sibling of DedicatedBot, PsychopathBot brings its philosophy to the extreme. It picks a bot at the beginning of the game and attempts to kill them. Once they are dead, it checks if it got shot by anyone (which it should have been). If it did, it picks them as its new target and does its best to take them out. Otherwise, it just chooses at random again and starts shooting.

```
package standoffKOTH;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class Player4Class extends PlayerClass {
    Random random = new Random();
    PlayerClass firstShot = null;
    public Player4Class()
    {
        super(10,0,0,0);
    }
    protected int makeMove()
    {
        List<PlayerClass> g = new ArrayList<PlayerClass>();g= this.getAliveEnemies();
        if (this.getAliveEnemies().contains(firstShot)) {;} else if(getShotBy()!=null) {firstShot = getShotBy();} else {firstShot = this.getAliveEnemies().get(random.nextInt(this.getAliveEnemies().size()));}
        if(getHP()<1)
        {return this.move('h', this);}
        else {
            if ((int)getAmmo()<2)
            {return this.move('r',this);}
            else {
            if(firstShot!=null&& g.contains(firstShot)) {
                if((int)getAmmo()>0){
                    return this.move('s',firstShot);}
                else{
                    return this.move('r',this);}}
            else{
                if(getShotBy()!=null&&getShotBy().deadQ()&&this.getAliveEnemies().size()!=0)
                {Collections.shuffle(g);return this.move('s',g.get(0));}
                else {return this.move('r', this);}}
    }}}
}

```

Generally, RevengeBot, DedicatedBot, and PsychopathBot split on subscore relatively closely, while RandomBot takes last. However, RevengeBot wins 50% of the games, while DedicatedBot wins around 10% (and RandomBot only wins 5%). This means that RevengeBot scores around 18000 points in a 5000 round match, while PsychopathBot scores 17000, DedicatedBot 16000, and RandomBot 3500.

# Answer
> 4 votes
## Destroyer

```
class Destroyer(PlayerClass):
    def __init__(self):
        super().__init__(10, 0, 0, 0)

    def makeMove(self):
        if self.health == 1:
            return "h"
        if self.ammo < 3:
            return "r"
        return "s", getAliveEnemies.get(0)  # destroy first enemy

```

---

Java version:

package standoffKOTH;

public class Destroyer extends PlayerClass {
    public Destroyer()
    {
        super(10,0,0,0);
    }
    protected int makeMove()
    {
        if(getHP()<2)
        {
            return move('h',this);
        }
        else if(getAmmo()<3)
        {
            return move('r',this);
        }
        else
        {
            return move('s',getAliveEnemies().get(0));}}}
```
</code></pre>

# Answer
> 3 votes
# WinnerBot

```
class WinnerBot:
    def __init__(self):
        super.__init__(5, 4, 1, 0)

    def makeMove(self):
        if self.health < 4:
            return "h"
        if self.ammo < 1:
            return "r"
        return "s", getShotBy()

```

# Answer
> 3 votes
# Tank

```
package standoffKOTH;
import java.util.concurrent.ThreadLocalRandom;

public class Tank extends PlayerClass {

    public Tank() {
        super(3, 1, 5, 1);
    }

    @Override
    protected int makeMove() {
        if (getHP() < 6 && ThreadLocalRandom.current().nextBoolean()) {
            return move('h', this);
        } else if (getAmmo() == 0) {
            return move('r', this);
        } else {
            PlayerClass lastShot = getShotBy();
            if (lastShot == null) {
                return move('r', this);
            } else {
                return move('s', lastShot);
            }
        }
    }
}

```

Simple bot with high armor and health. If its health is below 6, it has a 50% chance of healing itself. If it has an empty holster, it reloads. Otherwise, if nobody fired it it, it also reloads the holster. If someone fired at the bot, it fires back.

# Answer
> 3 votes
## HpKing

```
package standoffKOTH;

import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;

public class HpKing extends PlayerClass{
    // Keep a map of the amount of times an enemy (last) shot at us
    TreeMap<String, Integer> shotBy = new TreeMap<>();
    int previousHp;

    public HpKing(){
        super(10,0,0,0); // Health ftw!
        previousHp = getHP();
    }

    protected int makeMove() {
        // Update the shotBy-map with the latest enemy that shot at us
        if(getShotBy() != null && previousHp!=getHP()){
            shotBy.merge(getShotBy().getClass().toString(), 1, Integer::sum);
            previousHp = getHP();
        }
        // Remove any enemies from the shotBy-map that are already dead:
        shotBy.keySet().removeIf(enemyStr -> getAliveEnemies().stream().noneMatch(instance -> instance.getClass().toString().equals(enemyStr)));

        // If there are more than two enemies left: heal if we're not full, otherwise reload to get more ammo
        if(getAliveEnemies().size()>2){

        }

        // If we're not full health:
        if (getHP() < getMaxHP()){
            // If there are more than two enemies are left: heal!!
            if (getAliveEnemies().size() > 2)
                return move('h', this);
            // If there is more than one enemy left: only heal if we've below 10 HP:
            if (getAliveEnemies().size() > 1 && getHP() < 10)
                return move('h', this);
            // If there is just a single enemy left: just keep shooting and reloading, and hope for the best
        }

        // If we didn't have to heal, but are out of ammo: reload
        if(getAmmo()<1)
            return move('r', this);

        // If we didn't had to heal and still have ammo left: shoot the enemy that most frequently shot at us
        // (with priority to the more recent one, if multiple enemies shot at us an equal amount of times before):
        // If no one shot at us yet: shoot at a random enemy:
        return move('s',
                shotBy.isEmpty() ? getAliveEnemies().get((int)(Math.random()*getAliveEnemies().size()))
                        : getAliveEnemies().stream()
                        .filter(enemy -> enemy.getClass().toString().equals(
                                Collections.max(shotBy.descendingMap().entrySet(), Map.Entry.comparingByValue()).getKey()))
                        .findFirst().get());
    }
}

```

This bot maxes out on HP for its 10 bonus values.
At the start, this bot's entire focus is to stay alive and keep its health at its maximum.
From the moment just two enemies are left alive: it's a bit more lenient with its health and starts focusing more on shooting (but still tries to keep its HP above 10 at all time).
From the moment just a single enemy is left: it just keeps reloading/firing and hopes for the best.

# Answer
> 2 votes
# SmartBot

```
package standoffKOTH;

import java.util.ArrayList;
import java.util.List;

public class SmartBot extends PlayerClass {
 private PlayerClass lastFired;
 public SmartBot() {
  super(0, 5, 3, 2);
 }
 protected int makeMove() {

  if (getHP() < 5) {
   return this.move('h', this);
  }
  if (getAmmo() < 2) {
   return this.move('r', this);
  }
  List<PlayerClass> enemies = new ArrayList<PlayerClass>();
  enemies = getAliveEnemies();
  for (int i = 0; i < enemies.size(); i++) {
   PlayerClass enemy = enemies.get(i);
   if (!(enemy instanceof RageBot3) && enemy.equals(lastFired)) {
    return this.move('s', enemy);
   }
  }
  lastFired =getShotBy();
  if (getHP() < 10) {
   return this.move('h', this);
  }
  return this.move('s', enemies.get(0));
 }
}

```

Or perhaps not too smart.

As I mentioned before, I suck at Java, so please correct any glaring errors you see. Also, if this bot fails to work during any test runs, please notify me of the error so I can correct my code. Hopefully I got it right.

This bot is quite conservative. If its HP is below 5, it will heal itself.

If its ammo is below 2, it will reload. (But only if its HP is 5 or more.)

Otherwise... it first tries to see if the same bot fired at it twice in a row. Or at least it tries to. Unless two different bots fire at it in a row, `lastFired` will be the same as before, so essentially if nobody has fired at SmartBot for a long time, SmartBot will just keep firing at the last person who shot at it.

If the above condition is true, it fires at that bot. Otherwise...

If its HP is below 10, it just heals itself (as a precautionary measure), otherwise it just shoots at the first bot in the list that is `getAliveEnemies()`.

And because RageBot3 seems to absolutely hate me, I have returned the favor.

So you see... pretty dumb after all.

# Answer
> 2 votes
# NormalBot

```
class NormalBot(PlayerClass):
    def __init__(self):
        super().__init__(6, 1, 3, 0)

    def makeMove(self):
        if self.health < 5:
            return "h"
        if self.ammo < 4:
            return "r"

        if getShotBy() is None:
            return "rh"[self.health > 5]

        return "s", last_enemy_who_attacked_me()

```

---

Java version:

```
package standoffKOTH;
public class NormalBot extends PlayerClass {
    public NormalBot()
    {
        super(6,1,3,0);
    }
    protected int makeMove()
    {
        if(getHP()<5)
        {
            return move('h',this);
        }
        else if (getAmmo()<4)
        {
            return move('r',this);
        }
        else if (getShotBy()!=null)
        {
            return move('s',getShotBy());
        }
        else if (getHP()<5)
        {
            return move('h',this);
        }
        else
        {
            return move('r',this);
        }}}

```

# Answer
> 2 votes
## OneVsOneMeBro

```
package standoffKOTH;

public class OneVsOneMeBro extends PlayerClass{
    public OneVsOneMeBro(){
        super(9,0,0,1); // Sacrifice 1 HP for 1 Speed
    }

    protected int makeMove() {
        // If there are more than one enemy left:
        // heal if we're not max, otherwise reload to get more ammo
        if (getAliveEnemies().size()!=1) {
            if (getHP()<getMaxHP())
                return move('h', this);
            else
                return move('r', this);
        }
        // If we're out of ammo: reload
        if (getAmmo()<1)
            return move('r', this);
        // Just a single enemy left, and we have ammo: shoot, shoot, shoot!
        return move('s', getAliveEnemies().get(0));
    }
}

```

As long as there is more than one enemy left: just heal if we're not max, otherwise gain ammo.
And as soon as just a single enemy is left: keep shooting, unless we have to reload.

Also uses a speed of `1`, so it has a higher chance of going first in the final 1vs1 versus the bots with speed `0`.

# Answer
> 2 votes
# WhatABot

```
package standoffKOTH;

import java.util.ArrayList;
import java.util.List;

public class WhatABot extends PlayerClass {
    List<Class> randomShooters = List.of(FriendlyAndHealthyBot.class, FriendlyNotFriendlyBot.class, HpKing.class, RageBot.class, RageBot2.class, Player2Class.class);
    List<Class> wontShootFirst = List.of(Dexter.class, WhatABot.class, Tank.class, NormalBot.class);
    List<PlayerClass> shot = new ArrayList<>();
    int turn = -1;

    public WhatABot() {
        super(10, 0, 0, 0);
    }

    protected int makeMove() {

        if (this.deadQ()) {
            return 0;
        }
        shot.removeIf(PlayerClass::deadQ);
        turn++;

        // if there's only 1 enemy left, or I'm currently getting attacked, just spam shoot
        PlayerClass immediateTarget = null;
        if (this.getShotBy() != null && !this.getShotBy().deadQ()) {
            immediateTarget = this.getShotBy();
            // only retaliate if its not some bot randomly firing
            if (!shot.contains(immediateTarget)) {
                for (Class randomShooter : randomShooters) {
                    if (randomShooter.isInstance(immediateTarget)) {
                        immediateTarget = null;
                        break;
                    }
                }
            }
        }
        if (getAliveEnemies().size() == 1) {
            immediateTarget = this.getAliveEnemies().get(0);
            // if the bot won't shoot unless shot first, heal up and fill up ammo before engaging
            if (!shot.contains(immediateTarget) && !this.getWhoShotYou().contains(immediateTarget)) {
                for (Class bot : wontShootFirst) {
                    if (bot.isInstance(immediateTarget)) {
                        if (getHP() < getMaxHP()) {
                            return this.move('h', this);
                        } else if (getAmmo() < 40 && getAmmo() + turn < 250) {
                            return this.move('r', this);
                        }
                    }
                }
            }
        }
        if (immediateTarget != null) {
            if (getAmmo() == 0) {
                return this.move('r', this);
            } else {
                shot.add(immediateTarget);
                return this.move('s', immediateTarget);
            }
        }

        if (shot.size() > 0) {
            if (getHP() < 10) {
                return this.move('h', this);
            }
            if (getAmmo() == 0) {
                return this.move('r', this);
            }
            return this.move('s', shot.get(shot.size() - 1));
        }

        if (getHP() < getMaxHP()) {
            return this.move('h', this);
        }
        if (getAmmo() < 30 && getAmmo() + turn < 250) {
            return this.move('r', this);
        }

        // kill fast players first
        PlayerClass target = getAliveEnemies().get(0);
        if (target.getSpeed() <= this.getSpeed() && getAmmo() < 50 && getAmmo() + turn < 250) {
            return this.move('r', target);
        }
        shot.add(target);
        return this.move('s', target);
    }
}

```

Bot logic in comments.

# Answer
> 1 votes
# RageBot

```
class RageBot(PlayerClass):
    def __init__(self):
        super().__init__(10, 0, 0, 0)

    def makeMove(self):
        if self.health < 5:
            return "s", last_one_who_attacked_me()
        return "r"

```

---

Java version:

```
package standoffKOTH;
import java.util.Random;
public class RageBot extends PlayerClass {
    Random rand = new Random();
    public RageBot()
    {
        super(10,0,0,0);
    }
    protected int makeMove()
    {
        if(getHP()<5&&getShotAt()!=null)
        {
            return move('s',getShotAt());
        }
        else if (getHP()>4)
        {
            return move('r',this);
        }
        else
        {
            return move('s',getAliveEnemies().get(rand.nextInt(getAliveEnemies().size())));}}}

```

# Answer
> 1 votes
# Dexter

```
package standoffKOTH;

public class Dexter extends PlayerClass {
    public Dexter() {
        super(0, 10, 0, 0);
    }

    protected int makeMove() {
        if (getHP() < getMaxHP()) { // heal if we're not at full health
            return move('h', this);
        }

        if (getAmmo() == 0) { // reload if we have no bullets
            return move('r', this);
        } else if (getShotBy() != null) { // if someone shot at us, retaliate
            if (getAliveEnemies().contains(getShotBy())) { // only if they're alive
                return move('s', getShotBy());
            } else {
                return move('h', this); // heal otherwise
            }
        } else {
            return move('h', this); // heal if we cannot decide on an action
        }
    }
}

```

Dexter is a simple man. He puts all the points into his favorite skill Dexterity.

He also fixates on healing **a ton** now. After a ton of testing on my side this should make Dexter compete harder than before..

# Answer
> 1 votes
## RageBot3

```
class RageBot3(PlayerClass):
    def __init__(self):
        super().__init__(8, 1, 0, 1)

    def makeMove(self):
        target = getShotBy()
        if target.deadQ():
            for e in getAliveEnemies():
                if isinstance(e, SmartBot) and not e.deadQ():
                    target = e
                    return "r"

            return "s", getAliveEnemies().get(0)

        if self.health < 3:
            return "h"
        elif self.health < 10:
            return "s", target

        if self.ammo < 6:
            return "r"
        else:
            if self.health < 5:
                return "h"
            else:
                return "s", target

```

---

Java version:

<pre><code>package standoffKOTH;

import java.util.Random;

public class RageBot3 extends PlayerClass {
    Random rand = new Random();
    PlayerClass target = null;
    public RageBot3()
    {
        super(8,1,0,1);
    }
    protected int makeMove()
    {
        if(target==null||target.deadQ()) {
            if(getShotBy()!=null)
            {
                target = getShotBy();
            }
        else if(target==null||target.deadQ()) {
            for(PlayerClass p:getAliveEnemies())
            {
                if(p instanceof SmartBot)
                {
                    target=p;
                    break;
                }
            }
        }
        if(target==null||target.deadQ()) {
            target = getAliveEnemies().get(0);
        }
        }
        if(getHP()<3)
        {
            return move('h',this);
        }
        else if (getHP()<10)
        {
            return move('s',target);
        }
        else if (getAmmo()<6)
        {
            return move('r',this);
        }
        else if (getHP()<5)
        {
            return move('h',this);
        }
        else
        {
            return move('s',target);
        }
    }
}
```

# Answer
> 1 votes
# StrategicBot

It has different strategies depending on the dynamics of the game.

`friendliness = remaining players / total number of players` with a deduction if it is being attacked two times in a row by someone.

It targets the last player who attacks it or the next player in the current round.

It tends to heal and reload when the friendliness is higher.

package standoffKOTH;

public class StrategicBot extends PlayerClass
{
    int total;
    PlayerClass foe;

    public StrategicBot()
    {
        super(10, 0, 0, 0);
        this.total = this.getPlayers().size();
    }

    @Override
    protected int makeMove()
    {
        float friendliness;
        // The bot gets more aggressive when there are fewer players
        if (this.getAliveEnemies().size() == 1)
            friendliness = 0;
        else
            friendliness = (float) this.getAliveEnemies().size() / total;

        // When being repeatedly attacked by someone, act more aggressively
        if (this.foe != null && this.foe == this.getShotBy())
            friendliness -= 0.5;

        if (this.foe.deadQ())
            this.foe = null;

        PlayerClass nextTarget;
        if (this.getShotBy() != null && !this.getShotBy().deadQ())
            nextTarget = this.getShotBy();
        else
            nextTarget = this.getAliveEnemies().get(0);

        if (this.getAmmo() == 0)
            return this.move('r', this);

        if (friendliness > 0.7) {
            if (this.getHP() < this.getMaxHP())
                return this.move('h', this);
            else if (this.getAmmo() < 15)
                return this.move('r', this);
        }
        else if (friendliness > 0.35) {
            if (this.getHP() < 12)
                return this.move('h', this);
            else if (this.getAmmo() < 8)
                return this.move('r', this);
        }
        else if (friendliness > 0.15) {
            if (this.getAmmo() < 2)
                return this.move('r', this);
            else if (this.getHP() == 3)
                // heal so there won't be a instakill
                // probably less valuable when HP < 3
                return this.move('h', this);
        }
        // Does not do anything else when friendliness <= 0.15
        return this.move('s', nextTarget);
    }
}
```
</code></pre>

# Answer
> 0 votes
## RageBot2

```
class RageBot2(PlayerClass):
    def __init__(self):
        super().__init__(8, 1, 1, 0)

    def makeMove(self):
        if self.health < 3:
            return "h"
        elif self.health < 10:
            return "s", last_one_who_attacked_me()

        if self.ammo < 6:
            return "r"
        else:
            if self.health < 8:
                return "h"
            else:
                return "s", last_one_who_attacked_me()

```

---

Java version:

```
package standoffKOTH;

import java.util.Random;

public class RageBot2 extends PlayerClass {
    Random rand = new Random();
    public RageBot2()
    {
        super(8,1,1,0);
    }
    protected int makeMove()
    {
        if (getHP()<3)
        {
            return move('h',this);
        }
        else if (getHP()<10&&getAmmo()>0&&getShotBy()!=null&&!getShotBy().deadQ())
        {
            return move('s',getShotBy());
        }
        else if (getAmmo()<6)
        {
            return move('r',this);
        }
        else if (getHP()<8)
        {
            return move('h',this);
        }
        else if (getShotBy()!=null&&getAmmo()>0&&!getShotBy().deadQ())
        {
            return move('s',getShotBy());
        }
        else if (getAmmo()<1)
        {
            return move('r',this);
        }
        else
        {
            return move('s',getAliveEnemies().get(rand.nextInt(getAliveEnemies().size())));}}}

```

This bot hopes to be RageBot, but smarter.

# Answer
> 0 votes
# ChargeBot

```
class ChargeBot(PlayerClass):
    def __init__(self):
        super().__init__(5, 0, 0, 5)

    def makeMove(self):
        if self.ammo == 0:
            return "r"
        if self.health < 7:
            return "h"
        return "s", alive_enemies()[-1]  # target slowest

```

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


title: Translate Text into Matoran

text:
# Question
Title: Translate Text into Matoran
The Matoran Alphabet is the alphabet used by many of the characters in the Bionicle universe.

Your challenge is to create a program or function that takes a string as input and creates an image of the input written in the Matoran alphabet.

The input will only consist of uppercase letters (A-Z), numbers (0-9), and spaces. You may instead take input in lowercase.

## Glyphs

As you can probably notice, the alphabet comprises glyphs made up of circles and straight lines.

For the sake of this challenge, let's define each glyph as a circle of radius 4 units (8 x 8), with some internal designs. The internal designs of letters can be any of:

* Vertical Line at position 2, 4, or 6 (either full length or half)
* Horizontal Line equivalent to above
* Circle of radius 1, centered at \[2, 2\], \[2, 6\], \[6, 2\], or \[6, 6\]
* Any of the above rotated by 45 degrees about the centre

Note that for some glyphs (notably D, H, and K) only some of the drawn parts have the rotation applied.

Number glyphs work slightly differently; they always have a circle of radius 1 in the centre. For numbers 0 - 5, the glyph has evenly spaced spokes between the circles, starting from the top. For numbers greater than 5, the glyph has an additional circle of radius 2 in the centre, and the number of spokes is 6 less than the number.

Here is a diagram of the glyphs in spec, any glyphs with 45 degree rotations have an orange grid.

For drawing the glyphs, any line stroke in the range (0, 1) can be used. Glyphs can be kerned (space between adjacent glyphs) any amount from 0 - 4 units. Spaces should be 8 units wide (in addition to kerning).

This is a code-golf challenge, so the shortest code in bytes in each language wins.

# Answer
# Java 10, ~~1291~~ ~~1271~~ 1265 bytes

```
import java.awt.*;a->new Frame(){Graphics G;void o(int x,int y,int s){G.drawOval(x,y,s,s);}void l(int...c){G.drawLine(c[0],c[1],c[2],c[3]);}public void paint(Graphics g){G=g;int x=10,A=20,B=40,C,D=60,E=70,F=80,G=100,H=120,I,J;for(var c:a){C=x+B;I=x+67;J=x+30;if(c>32){o(x,B,F);if(c<58){o(J,E,A);if(c>53){o(x+A,D,B);if(c>56){l(C,B,C,D);l(x+22,90,x+7,G);l(x+58,90,x+73,G);}else{if(c>54)l(C,B,C,D);if(c>55)l(C,G,C,H);}}else{if(c>52){l(C,B,C,E);l(x+2,69,x+31,77);l(x+78,69,x+49,77);l(x+34,87,x+17,112);l(x+46,87,x+63,112);}else if(c==51){l(C,B,C,E);l(x+32,85,x+7,G);l(x+48,85,x+73,G);}else{if(c>48)l(C,B,C,E);if(c>49)l(C,90,C,H);if(c>51){l(x,F,J,F);l(x+50,F,x+F,F);}}}}else{var q=c+"";if("BHUV".contains(q))o(J,B,A);if(c>66&c<69|c==87)o(x+D,E,A);if(c<67|c==72)o(J,G,A);if(c==87)o(x,E,A);if(c>81&c<84|c==F)o(x+50,50,A);if(c==76|c==81)o(x+50,90,A);if(c==74|c==83)o(x+10,90,A);if("DGIJLPR".contains(q))l(C,B,C,H);if(c==71|c==82|c==84)l(C,F,x+F,F);if(c==84)l(C,F,C,H);if(c==75|c==84)l(x,F,C,F);if("KVWXYZ".contains(q))l(C,F,I,52);if("KNVWXY".contains(q))l(C,F,I,108);if("VWXZ".contains(q))l(x+13,108,I,52);if("NVWXY".contains(q))l(x+13,52,I,108);if(c>68&c<71){l(x+5,D,x+75,D);if(c<70)l(x+5,G,x+75,G);}if(c==72|c==77){l(x+A,45,x+A,115);l(x+D,45,x+D,115);}}}x+=F;}}{show();}}

```

Input as a character-array. Output with a unit being 10 pixels without kerning.

Some example I/O screenshots:

`"1357902468"`:

`"KEVIN CRUIJSSEN"`:

`"MATORAN ALPHABET"`:

```
import java.awt.*;                   // Required import for Frame and Graphics
a->                                  // Method with char-array parameter and Frame return-type
  new Frame(){                       //  Create the Frame
    Graphics G;                      //   Put a Graphics instance on class-level
    void o(int x,int y,int s){       //   Create a shorter method `o` for drawOval
      G.drawOval(x,y,s,s);}          //    Draw a circle with width/height `s` with its top-left corner of a virtual surrounding square at position `x,y`
    void l(int...c){                 //   Create a shorter method `l` for drawLine
      G.drawLine(c[0],c[1],c[2],c[3]);}
                                     //    Draw a line from x1,y1 to x2,y2
    public void paint(Graphics g){   //   Overwrite the Frame's paint method:
      G=g;                           //    Save its Graphics parameter in the class-level variable
      int x=10,                      //    Start the `x` position at 10 (for the left-side border of the Frame)
          A=20,B=40,C,D=60,E=70,F=80,G=100,H=120,I,J;
                                     //    Constants to save bytes
      for(var c:a){                  //    Loop over the characters `c`:
        C=x+B;I=x+67;J=x+30;         //     Set more constants that use variable `x`
        if(c>32){                    //     If `c` is NOT a space:
          o(x,B,F);                  //      Draw a big surrounding circle
          if(c<58){                  //      If `c` is a digit:
            o(J,E,A);                //       Draw the center circle
            if(c>53){                //       If `c` is larger than '5':
              o(x+A,D,B);            //        Draw the larger center circle
              if(c>56){              //        If `c` is '9':
                l(C,B,C,D);l(x+22,90,x+7,G);l(x+58,90,x+73,G);}
                                     //         Draw its three small lines
              else{                  //        Else (it's '6'/'7'/'8'):
                if(c>54)             //         If it's '7' or '8':
                  l(C,B,C,D);        //          Draw the small top vertical line
                if(c>55)             //         If it's '8':
                  l(C,G,C,H);}}      //          Also draw the small bottom vertical line
            else{                    //       Else (`c` is '5' or smaller):
             if(c>52){               //        If `c` is '5':
               l(C,B,C,E);l(x+2,69,x+31,77);l(x+78,69,x+49,77);l(x+34,87,x+17,112);l(x+46,87,x+63,112);}
                                     //         Draw its five small lines
             else if(c==51){         //        Else-if `c` is '3':
               l(C,B,C,E);l(x+32,85,x+7,G);l(x+48,85,x+73,G);}
                                     //         Draw its three small lines
             else{                   //        Else (`c` is '0'/'1'/'2'/'4'):
               if(c>48)              //         If `c` is larger than '0':
                 l(C,B,C,E);         //          Draw the top medium vertical line
               if(c>49)              //         If `c` is larger than '1' (thus '2'/'4'):
                 l(C,90,C,H);        //          Draw the bottom medium vertical line
               if(c>51){             //         If `c` is '4':
                 l(x,F,J,F);l(x+50,F,x+F,F);}}}}
                                     //          Draw its left/right lines
          else{                      //      Else (`c` is a letter):
            var q=c+"";              //       Transform the char to a String
            if("BHUV".contains(q))   //       If `c` is one of BHUV:
              o(J,B,A);              //        Draw the top small circle
            if(c>66&c<69|c==87)      //       If `c` is one of CDW:
              o(x+D,E,A);            //        Draw the right small circle
            if(c<67|c==72)           //       If `c` is one of ABH:
              o(J,G,A);              //        Draw the bottom small circle
            if(c==87)                //       If `c` is W:
              o(x,E,A);              //        Draw the left small circle
            if(c>81&c<84|c==F)       //       If `c` is one of PRS:
              o(x+50,50,A);          //        Draw the top-right small circle
            if(c==76|c==81)          //       If `c` is L or Q:
              o(x+50,90,A);          //        Draw the bottom-right small circle
            if(c==74|c==83)          //       If `c` is J or S:
              o(x+10,90,A);          //        Draw the bottom-left small circle
            if("DGIJLPR".contains(q))//       If `c` is one of DGIJLPR:
              l(C,B,C,H);            //        Draw the large vertical line
            if(c==71|c==82|c==84)    //       If `c` is one of GRT:
              l(C,F,x+F,F);          //        Draw the right horizontal line
            if(c==84)                //       If `c` is T:
              l(C,F,C,H);            //        Draw the bottom vertical line
            if(c==75|c==84)          //       If `c` is K or T:
              l(x,F,C,F);            //        Draw the left horizontal line
            if("KVWXYZ".contains(q)) //       If `c` is one of KVWXYZ:
              l(C,F,I,52);           //        Draw the top-right anti-diagonal
            if("KNVWXY".contains(q)) //       If `c` is one of KNVWXY:
              l(C,F,I,108);          //        Draw the bottom-right diagonal
            if("VWXZ".contains(q))   //       If `c` is one of VWXZ:
              l(x+13,108,I,52);      //        Draw the bottom-left anti-diagonal
            if("NVWXY".contains(q))  //       If `c` is one of NVWXY:
              l(x+13,52,I,108);      //        Draw the top-left diagonal
            if(c>68&c<71){           //       If `c` is E or F:
              l(x+5,D,x+75,D);       //        Draw the top horizontal line
              if(c<70)               //        If `c` is E:
                l(x+5,G,x+75,G);}    //         Draw the bottom horizontal line
            if(c==72|c==77){         //       If `c` is H or M:
              l(x+A,45,x+A,115);l(x+D,45,x+D,115);}}}
                                     //        Draw the left/right vertical lines
        x+=F;}}                      //     Increase `x` by 80 (8 units)
    {                                //   And then in an initializer-block:
      show();}}                      //    Show the Frame

```
> 10 votes

# Answer
# Python 3 + `pygame`, ~~1365~~ ~~1270~~ 1261 bytes

Full program that takes a string from stdin, and displays the glyphs in a window.

Edit -95 bytes: Now shorter than Java!!! I've lost track of what all I golfed, but theres a hell of a lot of constants in here that replace repeated numbers and tuples, and various other stuff. Also note that the `\x0c`s on line 8 represent literal ASCII formfeeds (codepoint `0C`)

Edit: @Steffan pointed out a few mistakes that were breaking code, fixed them.

Edit -9 bytes: Take this Java!! Big thanks to user in chat for helping me golf down the number section

```
from pygame import*
from math import*
A,c,l,S,d,T,U,V,W,X,Y,Z,I="red",draw.circle,draw.line,Surface,display,(w:=16,4),(x:=32,0),(w,60),(v:=48,60),(x,x),(y:=64,y),(x,y),()
def L(C,L,R,E):
 s=S(Y);c(s,A,X,x,1);_={0:(T,V),1:(U,Z),2:((v,4),W),4:(X,Z),5:((4,w),(60,w)),6:((0,x),(y,x)),7:((4,v),(60,v)),8:((0,x),X),9:(X,(y,x))}
 for i in C:c(s,A,{1:(v,w),2:(v,v),3:(w,v)}[i],8,1)
 for i in L:l(s,A,*_[i])
 if R:s=transform.rotate(s,R*45).subsurface(*b'\x0c\x0cKK')
 for i in E:l(s,A,*_[i])
 return s
def N(n):
 s=S(Y);exec(3*"c(s,A,X,%i,1);"%(x,8,n//6*w))
 for i in range(a:=n%6):z=lambda r:(x+r*sin(b:=2*pi*i/a),x-r*cos(b));l(s,A,z(8+n//6*8),z(x))
 return s
t=input()
s=d.set_mode((y*len(t),y))
for i in range(len(t)):s.blit(L(*{"A":([3],I,1,I),"B":((1,3),I,1,I),"C":([2],I,1,I),"D":([2],I,1,[1]),"E":(I,(5,7),0,I),"F":(I,[5],0,I),"G":(I,(1,9),0,I),"H":((1,3),I,1,(0,2)),"I":(I,[1],0,I),"J":([3],[1],0,I),"K":(I,(4,9),1,[8]),"L":([2],[1],0,I),"M":(I,(0,2),0,I),"N":(I,[1],1,I),"O":(I,I,0,I),"P":([2],[1],0,I),"Q":([2],I,0,I),"R":([1],(1,9),0,I),"S":((1,3),I,0,I),"T":(I,(4,6),0,I),"U":([1],I,1,I),"V":([1],(1,6),1,I),"W":((1,3),(1,6),-1,I),"X":(I,(1,6),1,I),"Y":(I,(1,9),1,I),"Z":(I,[6],1,I),}[t[i]])if t[i].isalpha()else N(int(t[i]))if" "!=t[i]else S(Y),(y*i,0))
d.flip()

```

Some sample outputs:

`HELLO WORLD`:

`0123456789`:

`MATORAN TESTING`:

## Ungolfed and (somewhat) explained version

```
from pygame import*
from math import*
W="red"
def Letter(circles, lines, rot, extra): ## Function that contructs a letter glyph
    S = Surface((64,64)) ## Surface to draw on
    draw.circle(S,W,(32,32),32,1) ## Exterior circle
    for i in circles: ## Draw the small circles
        draw.circle(S,W,{0:(16,16),1:(48,16),2:(48,48),3:(16,48)}[i],8,1) ## This dict maps 0,1,2,3 to the different circle positions, clockwise from top left. Circle 0 is not used in the golfed version.
    for i in lines: ## Draw the lines
        draw.line(S,W,*{0:((16,4),(16,60)),1:((32,0),(32,64)), ## This dict maps numbers to the coords for various line segments.
                        2:((48,4),(48,60)),3:((32,0),(32,32)),4:((32,32),(32,64)), ## 0,1,2 are full length vertical lines, 4,5 are half length vertical lines
                        5:((4,16),(60,16)),6:((0,32),(64,32)),7:((4,48),(60,48)), ## 5,6,7 are full length horizontal lines, 8,9 are half length horizontal lines
                        8:((0,32),(32,32)),9:((32,32),(64,32))}[i]) ## 3 and 8 are not used in the golfed version
    if rot: ## rotate the glyph 45 degrees, if necessary
        S=transform.rotate(S,R*45).subsurface((12,12,75,75)) ## the R*45 is used in the golfed version to sometimes rotate the other direction, which allowed the removal of some circle/line keys from the dicts
    for i in extra: ## draw the extra line segments necessary, names the same as above for consistency
        draw.line(S,W,*{0:((16,4),(16,60)),1:((32,0),(32,64)),
                        2:((48,4),(48,60)),8:((0,32),(32,32))}[i])
    return S ## return the surface
def Number(n): ## contructs a number glyph from its value
    S = Surface((64,64)) ## Contruct a surface to draw on
    draw.circle(S,W,(32,32),32,1) ## Exterior circle
    draw.circle(S,W,(32,32),8,1) ## Central circle
    draw.circle(S,W,(32,32),16*(n//6),1) ## Larger central circle, radius 0 if unneeded (radius 0 == nothing drawn)
    for i in range(n%6): ## draw the spokes
        a,r=(2*pi*i)/(n%6),8+n//6*8 ## current angle and the radius of the central circle
        draw.line(S,W, ## draw the line, with appropriate endpoints
                  (32+sin(a)*r,32-cos(a)*r),
                  (32+sin(a)*32,32-cos(a)*32)
                  )
    return S ## return the surface
T=input().upper() ## take input from stdin, .upper() to make ungolfed version more friendly
s=display.set_mode((64*len(T),64)) ## setup the display wide enough for the input text
for i in range(len(T)): ## loop through the characters
    s.blit( ## blit (copy) the glyph surface onto the display
           Letter(*{"A":((3,),(),1,()),"B":((1,3),(),1,()),"C":((2,),(),1,()), ## if its a letter, this (somewhat scary) dict maps
                    "D":((2,),(),1,(1,)),"E":((),(5,7),0,()),"F":((),(5,),0,()), ## the letter to the correct args for Letter()
                    "G":((),(1,9),0,()),"H":((1,3),(),1,(0,2)),"I":((),(1,),0,()),
                    "J":((3,),(1,),0,()),"K":((),(4,9),1,(8,)),"L":((2,),(1,),0,()),
                    "M":((),(0,2),0,()),"N":((),(1,),1,()),"O":((),(),0,()),
                    "P":((1,),(1,),0,()),"Q":((2,),(),0,()),
                    "R":((1,),(1,9),0,()),"S":((1,3),(),0,()),"T":((),(4,6),0,()),
                    "U":((1,),(),1,()),"V":((1,),(1,6),1,()),
                    "W":((0,2),(1,6),1,()),"X":((),(1,6),1,()),
                    "Y":((),(1,9),1,()),"Z":((),(6,),1,()),}[T[i]])
           if T[i].isalpha() ## only send the char to Letter() if it is a letter
           else Number(int(T[i])) ## otherwise send it to Number() as an int
           if T[i]!=" " ## but if its a space, don't send it to either function
           else Surface((64,64)), ## instead just make a new, empty surface
           (64*i,0)) ## place at the right position
display.flip() ## render all chars

```
> 7 votes

# Answer
# HTML + JS + SVG, ~~577~~ ~~575~~ ~~571~~ ~~552~~ ~~545~~ ~~544~~ ~~522~~ ~~511~~ ~~497~~ ~~507~~ 503 bytes

*On my browser (Firefox 100 on Linux), the 0 and 6 used to render correctly, because an invalid `transform` hid the SVG elements. A few months later, I'm adding 10 bytes, since I can't seem to reproduce that anymore.*

```
t=>[...t,0].map(c=>document.body.innerHTML+=c?`<svg viewBox=-4,-4,8,8 width=50 fill=#fff stroke=#000 stroke-width=.1>`+(c>" "&&['D',..."Y Y] _ _` PT T J` RVY] ` Z` IKN X` RV c = `^ X J^` Z^ Lb ] ]ac [_ac ac Ic a".split` `[parseInt(c,36)-10]||(c%6?'()*+,':'')+(c>5?'BA':'A')].map(u=>`<path d=${`M57A5,57,177,5A5,5777,5784 M6,2H-6 M2,1939184v484`.replace(/./g,k=>[x=(y=u.charCodeAt())&7,3.4,',0',' M0,-4v','A1,1,0,0,0,2,'][k-5]||k).split` `[y>>3&7]} transform=rotate(${y<64?x*360/(c%6):45*x}) />`)):'<p>')

```

Or 493 bytes if you don't care about separating the outputs of different calls with `<p>`. (Replacing the page contents is longer.)

```
t=>[...t].map(c=>document.body.innerHTML+=`<svg viewBox=-4,-4,8,8 width=50 fill=#fff stroke=#000 stroke-width=.1>`+(c>" "&&['D',..."Y Y] _ _` PT T J` RVY] ` Z` IKN X` RV c = `^ X J^` Z^ Lb ] ]ac [_ac ac Ic a".split` `[parseInt(c,36)-10]||(c%6?'()*+,':'')+(c>5?'BA':'A')].map(u=>`<path d=${`M57A5,57,177,5A5,5777,5784 M6,2H-6 M2,1939184v484`.replace(/./g,k=>[x=(y=u.charCodeAt())&7,3.4,',0',' M0,-4v','A1,1,0,0,0,2,'][k-5]||k).split` `[y>>3&7]} transform=rotate(${y<64?x*360/(c%6):45*x}) />`)))

```

Or 482 bytes if you don't care about the colors at all:

```
t=>[...t].map(c=>document.body.innerHTML+=`<svg viewBox=-4,-4,8,8 width=50 stroke=red stroke-width=.1>`+(c>" "&&['D',..."Y Y] _ _` PT T J` RVY] ` Z` IKN X` RV c = `^ X J^` Z^ Lb ] ]ac [_ac ac Ic a".split` `[parseInt(c,36)-10]||(c%6?'()*+,':'')+(c>5?'BA':'A')].map(u=>`<path d=${`M57A5,57,177,5A5,5777,5784 M6,2H-6 M2,1939184v484`.replace(/./g,k=>[x=(y=u.charCodeAt())&7,3.4,',0',' M0,-4v','A1,1,0,0,0,2,'][k-5]||k).split` `[y>>3&7]} transform=rotate(${y<64?x*360/(c%6):45*x}) />`)))

```

Apparently, I had a very similar idea to @Matthew Jensen about SVG being *much* shorter than the other options. However, I took a pretty different approach.

I think this is finally getting pretty close to optimal with my current approach. If only I had a language with JS semantics but Python builtins, like `int()`, `str.translate`, `oct`, `str[:]`, …

The output may be wrapped on small screens or if your Stack Snippet is not fullscreen. (You can reduce `width=50` to fix this.)

```
renderMatoran =

t=>[...t,0].map(c=>document.body.innerHTML+=c?`<svg viewBox=-4,-4,8,8 width=50 fill=#fff stroke=#000 stroke-width=.1>`+(c>" "&&['D',..."Y Y] _ _` PT T J` RVY] ` Z` IKN X` RV c = `^ X J^` Z^ Lb ] ]ac [_ac ac Ic a".split` `[parseInt(c,36)-10]||(c%6?'()*+,':'')+(c>5?'BA':'A')].map(u=>`<path d=${`M57A5,57,177,5A5,5777,5784 M6,2H-6 M2,1939184v484`.replace(/./g,k=>[x=(y=u.charCodeAt())&7,3.4,',0',' M0,-4v','A1,1,0,0,0,2,'][k-5]||k).split` `[y>>3&7]} transform=rotate(${y<64?x*360/(c%6):45*x}) />`)):'<p>')

for (const text of ["ABCDEFGHIJ","KLMNOPQRST", "UVWXYZ", "0123456789", "CODE GOLF 101"]) {
  renderMatoran(text);
}
```

### Explanation

```
t =>
  [...t, 0].map(c =>  /* for each char c (plus terminator) ... */
    document.body.innerHTML +=  /* the HTML parser will enjoy this... */
    c ?                         /* handle terminator */
    `<svg
      viewBox=-4,-4,8,8         /* we want nice and short coords */
      width=50                  /* specify some width so the browser */
                                /* puts our svgs next to each other */
      fill=#fff stroke=#000
      stroke-width=.1           /* much cheaper than big coords */
    >` +
    (c > " " &&  /* yield false if space (gets dumped in the SVG, */
                 /* but it does not care about stray strings) */
    ['D',    /* everything has a big circle */
    ...      /* convert rest to array elements */
    "Y Y] _ _` PT T J` RVY] ` Z` IKN X` RV c = `^ X J^` Z^ Lb ] ]ac [_ac ac Ic a"
    .split` `[parseInt(c,36)-10] /* for letters: take corresponding item */
                                 /* from the data string */
    || `()*+,${c>5?'B':''}A`     /* for numbers: generate string with */
                                 /* 5 spokes and 1-2 circles */
    ].map(u =>  /* for each char u in the instructions... */
      `<path
        d=${  /* svg path black magic */
          `M57A5,57,177,5A5,5777,5784 M6,2H-6 M2,1939184v484`
          .replace(/./g, k => /* map each character k to... */
            [
              x = (y = u.charCodeAt()) & 7,  /* 5 -> instruction arg */
              3.4,                   /* 6 -> approx. 2*sqrt(3) */
              ',0',                          /* 7 */
              ' M0,-4v',                     /* 8 */
              'A1,1,0,0,0,2,'                /* 9 */
            ][k-5] || k                      /* everything else to itself */
          ).split` `[y>>3&7]  /* grab correct instruction */
        }
        transform=rotate(${
          y<64 ? x*360/(c%6)  /* rotation for spokes */
          : 45*x              /* rotation for everything else */
        })
      />`
    ))       /* just dump the array in the string, the parser will eat the */
             /* useless commas :) */
    : '<p>'  /* make sure each call goes on its own line */
  )

```
> 6 votes

# Answer
# BBC BASIC, ~~395~~ 385 bytes

```
I.s$
F.i=1TOLENs$c=ASCM.s$,i,1)MOD64IFc=32N.
ORIGIN80*i,80m=ASCM."CBDFFDFRFATETsDFDF?UDxhxsI",c,1)*95+ASCM."!~R8Kg\SJ?bs9?dD.VS{bN|PEu",c,1)t=m MOD2*20n=8m /=2v=t*7/4w=40-t
IFc>47n=c MOD6+1E-9m=728+(n<1)
a=PI*2/n
F.j=0TOa*n S.a:u=m MOD3m/=3y=COSj:x=SINj
IFu<1CIRCLEx*28,y*28,10
IFu>1L.x*t-y*v,y*t+x*v,x*w+y*v,y*w-x*v
N.F.k=5-c DIV27*2TO5j=k MOD5+1MOVE0,0PLOT155-j MOD2*10,0,40>>j/2N.N.

```

Download interpreter at http://www.bbcbasic.co.uk/bbcwin/bbcwin.html

Keyword abbreviations expand on loading into IDE.

**Explanation**

For letters, each of the 8 positions from N through E, S and W to NW can be either empty space, a line or a small circle. Additionally, the lines within each letter are usually radial, but for certain letters `EFHM` they are at right angles. The information for each letter is stored as an 8 digit ternary number, which is multiplied by 2 and the final bit indicates whether lines are radial or at right angles. Encoding is as follows to minimise the range of codes (there is never a circle in the NW position)

```
  MAIN ENCODING         LINE DIRECTION ENCODING
  0 = circle              0 = radial
  1 = space               1 = at right angles to radial
  2 = line

```

For digits, the number of spokes is reduced to the ASCII code mod 6, and it is assumed that all spaces are lines with the constant `728`. BBC BASIC `FOR` loops are always excecuted at least once, so where the ASCII code mod 6 is zero, the plotting of the first spoke is suppressed by subtracting 1 from the constant. `(n<1)` evaluates to TRUE which is represented in BBC BASIC by `-1`.

A radius of 40 was selected for each character. This is because of the well known approximations `40*SIN45=28` and `40*SIN60=35`

**Ungolfed code**

```
  INPUT s$                                     :REM input from stdin
  FOR i=1 TO LEN(s$)                           :REM for each character in input
    c=ASC(MID$(s$,i,1))MOD64                   :REM convert to ASCII code MOD 64 so that "A"=1
    IF c=32NEXT                                :REM if it is a space do nothing
  ORIGIN 80*i,80                               :REM move graphics origin to the cente of the current letter
  m=ASC(MID$("CBDFFDFRFATETsDFDF?UDxhxsI",c,1))*95+ASC(MID$("!~R8Kg\SJ?bs9?dD.VS{bN|PEu",c,1))
  t=m MOD2*20                                  :REM use the 2 magic strings to lookup the letter data m
  m/=2                                         :REM t indicates if lines are radial. Extract t and divide by 2
  v=t*7/4                                      :REM for nonradial lines, tangential offset of 20*7/4=35 is needed
  w=40-t                                       :REM radial offest of line endpoint is 40 for radial, 20 for nonradial
  n=8                                          :REM 8 spokes for letters
  IF c>47 n=c MOD 6+1E-9:m=728+(n<1)           :REM if character is a digit (c>47), there are c MOD6 spokes
  a=PI*2/n                                     :REM calculate angle between spokes (+1E-9 on previous line avoids division by 0)
  FOR j =0 TO a*n STEP a                         :REM iterate through spokes
    u=m MOD 3: m/=3                              :REM extract data u for current spoke then divide m by 3 for the next one
    y=COSj:x=SINj                                :REM calculate (x,y) vector for radial direction of current spoke
    IF u<1 CIRCLE x*28,y*28,10                   :REM if u=0 draw a circle instead of a spoke
    IF u>1 LINE x*t-y*v,y*t+x*v,x*w+y*v,y*w-x*v  :REM if u=2 draw a spoke starting at radius t=0 and ending at radius w=40
  NEXT                                           :REM if t=20 draw a nonradial line instead from -v to v passing through radius t=w=20
  FOR k=5-c DIV27*2TO5                         :REM iterate through circles: c>=54 k starts at 1; c>=27 k starts at 3, c<2 k starts at 5
    j=k MOD 5+1                                  :REM order of circles: 1+1=2, 2+1=3 (digits 6789); 3+1=4 4+1=5 (all digits); 0+1=1 (all symbols)
    MOVE 0,0:PLOT 155-j MOD2*10,0,40>>j/2        :REM clear the background for even number circles, draw the circle for odd number circles
  NEXT                                           :REM radius 40>>(2/2 or 3/2)=20, 40>>(4/2 or 5/2)=10, 40>>(1/2) = 40
  NEXT                                         :REM repeat for next character

```
> 6 votes

# Answer
# JavaScript + HTML, 582 bytes

-many, many bytes thanks to tsh!

Changed it to modify `document.body` to better match this other JS + HTML answer.

```
s=>document.body.innerHTML+=`<svg viewBox=5,-5,${[c,l]=['<circle r=cx=cy=','<line y2=y1=x2=x1='].map(n=>(...a)=>n[$](/=/g,_=>`=${a.pop()} `)+`transform=rotate(${R*45}) />`),s.length}0,10 stroke=red stroke-width=.2>`+s.toLowerCase()[$='replace'](/./g,x=>'<g transform=translate(10)>'+(x>' '&&c(R=0,4)+(1/x?[...Array(L=x%6)].map(_=>(R+=8/L,l(-4)))+[x>5&&c(2)]+c(1):'aC1bC1C5cC7dC7LeE2E6fE6gI6LhC1C5E4EiLjC2LkI2I5I7lC0LmE4EnL3pC6LqCrC6I6LsC2C6tL2IuC5vC5L1L3wC3C7L1L3xL1L3yL3I5zL1'.match(x+'([0-Z]+)')?.[1][$](/..?/g,([z,r])=>(R=r,{C:c(2,2,1),L:l(-4,4),I:l(4),E:l(2,2,-3.5,3.5)}[z])))))

```

```
f=
s=>document.body.innerHTML+=`<svg viewBox=5,-5,${[c,l]=['<circle r=cx=cy=','<line y2=y1=x2=x1='].map(n=>(...a)=>n[$](/=/g,_=>`=${a.pop()} `)+`transform=rotate(${R*45}) />`),s.length}0,10 stroke=red stroke-width=.2>`+s.toLowerCase()[$='replace'](/./g,x=>'<g transform=translate(10)>'+(x>' '&&c(R=0,4)+(1/x?[...Array(L=x%6)].map(_=>(R+=8/L,l(-4)))+[x>5&&c(2)]+c(1):'aC1bC1C5cC7dC7LeE2E6fE6gI6LhC1C5E4EiLjC2LkI2I5I7lC0LmE4EnL3pC6LqCrC6I6LsC2C6tL2IuC5vC5L1L3wC3C7L1L3xL1L3yL3I5zL1'.match(x+'([0-Z]+)')?.[1][$](/..?/g,([z,r])=>(R=r,{C:c(2,2,1),L:l(-4,4),I:l(4),E:l(2,2,-3.5,3.5)}[z])))))

;

[
  'Hello World',
  'Matthew Jensen',
  'Matoran Alphabet',
  'ABCDEFGHIJ',
  'KLMNOPQRST',
  'UVWXYZ',
  '0123456789',
].forEach(text => {
  f(text);
  //document.body.appendChild(document.createElement('div')).innerHTML = f(text);
});
```

```
svg {
  background-color: black;
  height: 64px;
}
```

Explained a bit

```
s => document.body.innerHTML += `<svg viewBox=5,-5,${ // add a new SVG element to doc body
  [c, l] = [ // define function to generate circle and line
    '<circle r=cx=cy=',
    '<line y2=y1=x2=x1='
  ].map(n => (...a) => // map each above string to function to assign args (reverse order)
    n[$ /* = 'replace' */ ](/=/g, _ => `=${a.pop()} `) +
    `transform=rotate(${R * 45}) />`), // apply 1/8 rotations by global R
    s.length
}0,10 stroke=red stroke-width=.2>` +
  s.toLowerCase()[$ = 'replace'](/./g, x => // replace each char with its svg
    '<g transform=translate(10)>' + // begin new group (nested in previous char, idea from tsh!)
    (x > ' ' && c(R = 0, 4) + // if not a space, draw the large circle
      (1 / x ? // if char is number
        [...Array(L = x % 6)] // draw line segments
          .map(_ => (R += 8 / L, l(-4))) +
        [x > 5 && c(2)] + // draw r=2 circle if >5
        c(1) // draw r=1 circle
      : // otherwise char is letter
        'aC1bC1C5cC7dC7LeE2E6fE6gI6LhC1C5E4EiLjC2LkI2I5I7lC0LmE4EnL3pC6LqCrC6I6LsC2C6tL2IuC5vC5L1L3wC3C7L1L3xL1L3yL3I5zL1'
          .match(x + '([0-Z]+)')?.[1] // find code for letter
          [$ /* = 'replace' */ ](/..?/g, ([z, r]) => ( // for each instruction [shape, rotation]
            R = r, // set global rotation to r
            { // look up instruction
              C: c(2, 2, 1),
              L: l(-4, 4),
              I: l(4),
              E: l(2, 2, -3.5, 3.5)
            }[z]
          )
        )
      )
    )
  )

```
> 5 votes

# Answer
# Perl 5 \+ `-M5.10.0 -lF`, 1017 bytes

```
sub d{unpack"B*",pop}sub a{$A[$_].="@_"eq''?0 x8:("@_"=~/.{17}/g)[$_]for 0..16}sub z{0 x pop}a{O,($x=d"........\$............`.0........0...."),A,$a=$x|z(194).($C=d"....D.\".."),U,$u=$x|z(24).$C,B,$b=$a|$u,C,$c=$x|z(114).$C,I,$i=$x|z(8).($l=d"..@. .............")|0 x($-=144).$l,D,$c|$i,F,$f=$x|z(70).($h=1x13),E,$f|z(206).$h,G,$g=$i|0 x$-.($H=1x9),M,$m=$x|z(38).($k=(1 .z 16)x13)|z(46).$k,H,$m|$b,J,$i|z(173).$C,K,$x|z(64).($y=d".."x6)|0 x$-.($Y=d".. ........ ")|z(135).$H,Q,$q=$x|z(181).$C,L,$i|$q,N,$n=$x|z(54).$Y|0 x$-.$Y,P,$p=$i|z(45).$C,R,$p|$g,S,$x|z(173).$C|z(45).$C,T,$g=$x|0 x$-.$H|z(135).$H|0 x$-.$l,Y,$z=$n|z(64).$y,X,$X=$z|0 x$-.$y,V,$X|$u,W,$X|z(104).$C|z(114).$C,Z,$x|z(64).$y|0 x$-.$y,0,$Z=$x|z(109).$C,1,$O=$Z|z(25).($L=d"..@. ...."),2,$T=$O|z(195).$L,3,$O|(z(174).d"...0"),4,$T|z(137).1111100000 x2,5,$O|(z(86).d"......`.0D......D..0."),6,$s=$x|(z(74).d".P....QF(..Q....P."),7,$S=$s|(z(25).($w=d"..@. ")),8,$S|z(229).$w,9,$S|z(180).(z(9).11)x2}->{$_}for@F;$-=y/ //c;say"P1 ",17*$-+8*(@F-$-)," 17 @A"
```

Try it online!

## Explanation

The main functionality of this answer utilises a lookup table to store information about each letter we translate, this lookup table is built up from previous letters and augmented using stringwise-OR operations.

We start with `O` which is just a circle. Using the PBM format, this is stored as:

```
00000111111100000
00011000000011000
00100000000000100
01000000000000010
01000000000000010
10000000000000001
10000000000000001
10000000000000001
10000000000000001
10000000000000001
10000000000000001
10000000000000001
01000000000000010
01000000000000010
00100000000000100
00011000000011000
00000111111100000

```

From here, `A` (for example) is augmented by ORing the string:

```
 1110000000000000
10001000000000000
10001000000000000
10001000000000000
01110

```

with a specific number of leading `0`s (194 for `A`), so as to place this at the right position.

The same technique is used to build the other letters and numbers, sometimes using the result of ORing two other letters to get the required output. The binary strings are stored using Perl's `pack` functionality and the data is output by repeatedly appending each required line from the letters to the list `@A`'s indices 0..16.

All the glyphs are hand-made by eye, so please shout if this is not to your liking!
> 4 votes

# Answer
# C (GCC), 871 bytes

```
#define Q(X,Y)(r=(X)*(X)+(Y)*(Y))
#define S(M)(y&M?-1:1)
#define C;for(y=1;y<16;y*=2)c|=x&y<<
#define A labs
int T[]={0,1,3,1,15,1,0,1,3,1,8192,12288,32768,32771,768,256,11,15360,3,131075,164,65539,3072,48,0,262147,65536,262155,393216,14,4096,4336,49392,240,176,192};main(i,v,j,k,x,r,y,n,c,w)char**v;{w=90*strlen(v[1]);printf("P5 %d %d 1 ",w,79);for(i=-40;i++<39;)for(j=-1;++j<w;putchar(c)){c=0;k=j%90-40;n=v[1][j/90];if(n-32){c|=Q(i,k)<1600&r>1400;x=T[n-48-7*(n>64)]C 0&&A(y&3?k:i)<2&k<40&(y&3?i:k)*S(5)>=0 C 4&&A(k)<28&A(i+k*S(3))<2&k*S(5)>=0 C 8&&A((y&3?i:k)-20*S(5))<2&A(i)<34&A(k)<34 C 12&&Q((y&3?i:k)-30*S(5),y&3?k:i)<99&r>63 C 16&&Q(i+20*S(3),k+20*S(5))<99&r>63;if(n<58){for(y=2;A(n-54)==3&&y--;)c|=A(1.73*i+k*S(y))<3&i>0&A(k)<34;for(y=2;n==53&&y--;)c|=A(3.08*i+k*S(y))<5&i<0&A(k)<39,c|=A(.73*i-k*S(y))<2&i>0&A(k)<23;if(n>53)c=(c|r<399)&r>323;c=(c|r<99)&r>63;}}}}

```

Attempt This Online!

Input is given via `argv[1]`. Outputs a PGM image.
> 3 votes

---
Tags: code-golf, kolmogorov-complexity, graphical-output
---


title: convert tabs to spaces

text:
# Question
Title: convert tabs to spaces
Write the shortest possible code which converts tabs to spaces in the input. Tab size should be supplied as a parameter or be hardcoded in the code **in a single place**.

Spaces on output should point to the right column, e.g. (`\t` represents a tab character):

```
a\tb
aa\tb
aaa\tb
aaaa\tb

```

should become (for tab size 4):

```
a   b
aa  b
aaa b
aaaa    b

```

Of course there can be more than one tab in a line.

Line separator and tab character should match the system defaults (e.g. ASCII 10 and 9 on Unix).

# Answer
> 2 votes
## Perl 5, 36 bytes

```
1while s/	/$"x($^I-length($`)%$^I)/e

```

Try it online!

Tab length is controlled with `-i` command-line parameter.

# Answer
> 2 votes
# Python 2, 106 bytes

```
def f(s,w):
 for l in s.split('\n'):
  L=''
  for x in l.split('\t'):L+=' '*(w-(len(L)%w))+x
  print L[w:]

```

Try it online!

# Answer
> 1 votes
# Vim, 16 bytes

```
:se ts=4 et
:ret

```

# Answer
> 1 votes
# Pyth, 24 bytes

```
VQ=+k:NJ"   "d=.[kd|nNJ4)k

```

Try it here

### Explanation

```
VQ=+k:NJ"   "d=.[kd|nNJ4)k
VQ                      )    For each character in the input...
  =+k:NJ"   "d               ... add the character with tab replaced by space
                             to k (initially empty)...
              =.[kd          ... then pad k with spaces...
                   |nNJ4     ... to the nearest multiple of 4 if the character
                             is a tab and 1 otherwise.
                         k   Output k.

```

Alternatively, if we want to input the tab length, we can do so with `Vz=+k:NJ" "d=.[kd|nNJQ)k`.
Try it here.

# Answer
> 0 votes
# Java 11, 134 bytes

```
n->s->{for(var l:s.split("\n")){var t="";for(var p:l.split("\t"))t+=" ".repeat(n-t.length()%n)+p;System.out.println(t.substring(n));}}

```

This time an answer for which I correctly read the challenge.. \>.\>

Try it online.
NOTE: Because Java 11 isn't on TIO yet, the `String.repeat(int)` has been emulated with `repeat(String,int)` for the same byte-count.

**Explanation:**

```
n->s->{                      // Method with int & String parameters and String return-type
  for(var l:s.split("\n")){  //  Split the input by newlines, and loop over the lines:
    var t="";                //   Temp-String, starting empty
    for(var p:l.split("\t")) //   Split the line by tabs, and loop over the parts
      t+=" ".repeat(n-t.length()%n)
                             //    Append `n - length_of_t modulo-n` amount of spaces,
         +p;                 //    as well as part `p` to the temp-String
      System.out.println(    //    Print with trailing new-line:
        t                    //     The temp-String `t`
         .substring(n));}}   //      after we've removed the trailing spaces

```

# Answer
> 0 votes
# Excel VBA, 118

An anonymous VBE immediate window function that takes an input string from range `[A1]` and an input tab length from range `[B1]`, and outputs to the console.

```
For Each l In Split([A1],vbLf):Do:i=InStr(1,l,"\t"):l=Replace(l,"\t",Space([B1]-(i-1)Mod[B1]),,1):Loop While i:?l:Next

```

### Ungolfed

```
Public Sub tabReplace(ByRef value As String, Optional tabLen As Integer = 4)
    Dim line, index As Integer
    For Each line In Split(value, vbLf)
        Do
            Let index = InStr(1, line, "\t")
            Let line = Replace(line, "\t", Space(tabLen - (index - 1) Mod tabLen), , 1)
        Loop While index
        Debug.Print line
    Next
End Sub

```

# Answer
> 0 votes
# Python 2, 103 bytes

```
def F(I,c):
 while'\t'in I:t=I.find('\t');I=I.replace('\t',' '*(c-(t+~I[:t].rfind('\n'))%c),1)
 print I

```

Try it online!

I wanted to evade `split` and use some `replace` (tbh I've started with regex).

I replace each `\t` with `c-(t+~I[:t].rfind('\n'))%c` number of spaces. Where `t` \- index of current `\t` and `t+~I[:t].rfind('\n')` is distance to the closest `\n` (or start of string) on left.

# Answer
> 0 votes
# Wolfram Language (Mathematica), 40 bytes

```
StringReplace[#,"	"->Array[" "&,4]<>""]&

```

Try it online!

Sadly, Mathematica doesn't let you multiply a string by a number to duplicate it, otherwise it would be shorter than Perl.

---

Explanation:

`StringReplace[#,` Replace all instances of

`" "` a tab character

`->Array[" "` with an array of spaces

`,4]` four long

`<>""]&` joined to the empty string.

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


title: Is Wally there?

text:
# Question
Title: Is Wally there?
*Inpired by recent Stand-up Maths' video.*

## Task

Wrapping a list `x` can be seen as inserting "line-breaks" into `x` every `n`-th element, or forming a matrix from `x` with `n` columns (feeding rows first). To be perfectly rigorous in the definition of `x` wrapped into a matrix, we can pad the last row with `0`s.

Given a list `x` of positive digits and a matrix `M` of positive digits, determine whether `x` can be wrapped into any matrix that contains `M` as a submatrix. In other words, is there any `n` such that wrapping `x` into a matrix of `n` columns results in a matrix that contains `M`?

## Rules

* Any reasonable input format is acceptable (list, string, array, etc.).
* As for output, please follow the defaults for decision-problem challenges.
* `x` is guaranteed to be longer than number of elements in `M`.
* You don't need to handle empty inputs.
* Some wrappings may result in the final line shorter - that's fine.
* This is , so make your code as short as possible.

## Examples

```
x=1231231
M=23
  31

Possible wrappings:
n>=7
1231231

n=6
123123
1

n=5
12312
31

n=4
1231
231

n=3
123
123
1

n=2
12
31
23
1

n=1
1
2
3
1
2
3
1

Output: True (4th wrapping)

```

```
x=1231231
M=23
  32
Possible wrappings: same as above
Output: False (none of the wrappings contain M as submatrix)

```

## Test cases

**Truthy**

```
x; M
[1,2,3,1,2,3,1]; [[2,3],[3,1]]
[3,4,5,6,7,8]; [[3,4,5],[6,7,8]]
[3,4,5,6,7,8]; [[3,4],[7,8]]
[1,2,3]; [[1,2,3]]
[1,2,3]; [[1],[2],[3]]
[1,1,2,2,3,3]; [[1],[2],[3]]
[1,1,3,4,5,6]; [[1],[4],[6]]

```

**Falsey**

```
x; M
[1,2,3,1,2,3,1]; [[2,3],[3,2]]
[1,1,2,2,3,3]; [[1,2,3]]
[1,2,3]; [[4,5,6]]
[1,2,3,4,5,6]; [[2,3],[4,5]]

```

# Answer
> 4 votes
# , ~~126~~ ~~121~~ 120 bytes

*Edit: -5 bytes thanks to Aaron Hayman*

```
function(x,m,r=nrow(m)){for(o in l<-seq(x)-1)for(s in l+o)T=T&any(c(x,!x,!x)[outer(1:r,(r+s)*(1:ncol(m)-1),`+`)+o]-m)
T}

```

Try it online!

Outputs `TRUE` if ~~wally isn't there~~ `m` is *not* present in any wrapping of `x`, `FALSE` if it is.

Calculates the indices of positions of ~~wally~~ `m` for each possible `o`ffset (the first position in the wrapped matrix) and `s`pacing (the width of the wrapped matrix), and checks that the elements of `x` at these indices are all equal to `m`.
To avoid lengthly calculations to keep the indices in-range, we first extend `x` with enough zeros to cover the biggest `o` & `s`: this is the ugly-looking `(c(x,!x,!x)`.

# Answer
> 4 votes
# , 21 bytes

```
1 e.,@(E."2-@#\]\"{])

```

Try it online!

Bulk of the work done by `E.` builtin, which can search for one 2D matrix within another, and even extends to higher dimensions.

* `-@#\]\"{]` Every possible wrapping.
* `E."2` Does the matrix match at each position? (returns 0/1 matrices)
* `,@` Flatten
* `1 e.` Is 1 an element of that?

# Answer
> 3 votes
# BQN, 24 bytesSBCS

Generates all possible wrappings and checks if the left argument is a submatrix of one.

```
{1∊∾(⥊⍷⥊˜⟨↑⟩∾1⊸+)¨↕≠}

```

Run online!

# Answer
> 2 votes
# PARI/GP, 100 bytes

```
f(a,b)=sum(n=#b,#a,!!matrix(-#a\-n,n-#b+1,x,y,b==matrix(#b~,#b,i,j,if(#a>=k=(x+i-2)*n+y+j-1,a[k]))))
```

Attempt This Online!

Generates all possible wrappings, and all of their submatrices of the given size, and check if the second argument is one of them.

# Answer
> 2 votes
# Desmos, 133 bytes

```

f(L,M,w)=0^{\sum_{m=1}^K\sum_{X=w}^m\sum_{Y=0}^K\prod_{j=0}^{M.\length-1}\{M[j+1]=L[X+Ym+1-w+\mod(j,w)+\floor(j/w)m],0\}}
K=L.length

```
* L: list of positive digits (x in question)
* M: matrix, flattened because Desmos doesn't have 2D arrays
* w: width of M

Outputs 0 for truthy and 1 for falsey.

Try it on Desmos!

# Answer
> 1 votes
# Charcoal, ~~31~~ 30 bytes

```
ＦＥθ⪪θ⊕κＰ⊙ι⊙κ⊙ι⊙ξ⁼ηＥ✂ιλ⊕π¹✂σν⊕ς

```

Try it online! Link is to verbose version of code. Outputs a Charcoal boolean, i.e. `-` if it finds Wally, nothing if not. Explanation: Another answer that generates all submatrices of all wrappings.

```
ＦＥθ⪪θ⊕κ

```

Generate all wrappings of the list.

```
Ｐ⊙ι⊙κ⊙ι⊙ξ⁼ηＥ✂ιλ⊕π¹✂σν⊕ς

```

Check whether the matrix exists as a submatrix.

Unfortunately Charcoal only has 11 loop variables so I can't save a further byte like this:

```
⊙Ｅθ⪪θ⊕κ⊙ι⊙κ⊙ι⊙ξ⁼ηＥ✂ιλ⊕π¹✂σν⊕ς

```

Explanation:

```
  θ                             Input list
 Ｅ                              Map over digits
    θ                           Input list
   ⪪                            Wrapped to width
      κ                         Current index
     ⊕                          Incremented
⊙                               Any wrapping satisfies
        ι                       Current wrapping
       ⊙                        Any row satisfies
          λ                     Current row
         ⊙                      Any column satisifies
            ι                   Current wrapping
           ⊙                    Any row satisfies
              ξ                 Inner row
             ⊙                  Any column satisifies
                η               Input matrix
               ⁼                Equals
                   ι            Current wrapping
                  ✂   ¹         Sliced from
                    μ           Outer row index to
                      π         Inner row index
                     ⊕          Incremented
                 Ｅ              Map over rows
                         σ      Current row
                        ✂       Sliced from
                          ν     Outer column index to
                            ς   Inner column index
                           ⊕    Incremented
                                Implicitly print

```

# Answer
> 1 votes
# 05AB1E, ~~27~~ 21 bytes

```
.œεεŒIнgù}øεŒIgù€Q]˜à

```

Try it online or or verify all test cases or try it online with step-by-step debug-lines.

**Explanation:**

```
.œ           # Get all partitions of the first (implicit) input-list
  ε          # Map over each partition:
   ε         #  Map over each inner list:
    Œ        #   Get all sublists of this list
     I       #   Push the second input-matrix
      н      #   Pop and leave just its first row
       g     #   Pop and push its length to get the width of the matrix
        ù    #   Only leave all sublists of this length, to get all overlapping
             #   parts with a size equal to the width of the input-matrix
   }ø        #  After the inner map: zip/transpose; swapping rows/columns
     ε       #  Map over each list of lists:
      Œ      #   Get all sublists of this list
       I     #   Push the second input-matrix again
        g    #   Pop and push its length to get the height of the matrix
         ù   #   Only leave all sublists of this length, to get all matrices
             #   with the same dimensions as the input-matrix
          €  #   Map over each inner matrix:
           Q #    Check if its equal to the second (implicit) input-matrix
  ]          # Close both maps
   ˜         # Flatten
    à        # Get the maximum to check if any were truthy

```

---
Tags: code-golf, array, decision-problem
---