title: Play Antichess!

text:
# Question
Title: Play Antichess!
https://en.wikipedia.org/wiki/Losing\_chess

This is basically Chess Tournament, but for antichess ;)

Antichess is one of the many chess variants that have been invented. The goal is to lose all your pieces (this may seem a little odd, but it's called antichess for a reason).

## The rules

The rules of antichess are very similar to standard chess - but with a few fairly minor differences. The goal as I mentioned above is to lose all your pieces. To make this happen, if your opponent has an opportunity to capture one of your pieces, that is the only move he can make. If you give him multiple chances in one turn, the other player may choose his turn. Another thing that is changed is that the king has no special powers - as in you cannot checkmate your opponent, and you can't force him into check.

The following changes to the standard game will also apply (they help simplify the game):

* *En passant* will be ignored.
* *Castling* isn't possible.
* The *Fifty-move rule* applies automatically (meaning the game ends in a draw).
* Pawns will be able to choose what they promote to.
* If a player needs longer than 2 seconds to move, he will lose the game.
* Returning an invalid move will result in losing the game.
* **To win, your opponents must capture all your pieces**.
* White begins the game.
* White is placed "at the bottom" of the field (y=0), black is located at the top (y=7).
* Accessing other resources than your bot (internet, files, other bots, ...) is prohibited.

## Scoring

* Winning grants you 3 points, a draw 1 point and losing 0 points.
* Each submission will play against each other submission 10 times (5 times as white, 5 as black).

## Writing your bot

### Controller code is here: https://github.com/JJ-Atkinson/SimpleAntichessKOTH

You can write your bot in either Java or Groovy. To write a bot you must extend the `Player` class. The player class has one abstract method `Move getMove(Board board, Player enemy, Set<Move> validMoves)`.

Here is a quick rundown on useful methods:

### `Player`:

* `List<Piece> getPieces(Board board)`: Return all your pieces that are on the board.
* `PieceUpgradeType pieceUpgradeType`: If/when one of your pawns reaches the end of the board, you will need to define this to the type of piece you want to upgrade to. You have the choice of `ROOK`, `KNIGHT`, `QUEEN`, `BISHOP`, and `KING`.

### `Board`:

* `Field getFieldAtLoc(Location loc)`: Return the `Field` at the location. This has a matching `getAt` method so that if you are using groovy you can write `board[loc]`.
* `Field getFieldAtLoc(int x, int y)`: Return the `Field` at the location. This has a matching `getAt` method so that if you are using groovy you can write `board[x, y]`.
* `Board movePiece(Player player, Move move)`: Make a move on the board so you can see how it would play out. It returns the new board.

If you want to see your opponents pieces, just write `enemy.getPieces(board)`. To add your bot to the lineup add the following line to `PlayerFactory`:

```
put(YourBot.class, { new YourBot() } )

```

## Debugging your bot:

I have included a couple of tools to aid in debugging your bots. To see your game played out live you can set the `Game#DEBUG` flag to true. You will get an output something like this:

```
Game started. Players: [OnePlayBot(WHITE), SacrificeBot(BLACK)]
...
BLACKs turn.
validMoves: [Move(Piece(BLACK, PAWN, Loc(0, 6)), Loc(0, 5)), ...]
board:
RKBQIBKR
PPPPPPPP
--------
--------
--------
p-------
-ppppppp
rkbqibkr

captureless turns: 1
chosen move: Move(Piece(BLACK, PAWN, Loc(7, 6)), Loc(7, 4))
Game over? false

==============================

WHITEs turn.
validMoves: [Move(Piece(WHITE, ROOK, Loc(0, 0)), Loc(0, 1)), ...]
board:
RKBQIBKR
PPPPPPP-
--------
-------P
--------
p-------
-ppppppp
rkbqibkr

...

```

(White is upper case, the king is shown with `i`)

If your console supports utf-8 special chars, you can even show the board with the chess chars by using `Board#USE_UTF8_TO_STRING`:

```
♜♞♝♛♚♝—♜
♟—♟♟♟♟♟♟
————————
—♟——————
————————
♙———————
—♙♙♙♙♔♙♙
♖♘♗♕—♗♘♖

```

(it looks better with a mono spaced font)

To prevent a flood of unwanted output, you should change the `Main#main` function to something like this:

```
new Game(new MyBot(), new SacrificeBot()).run()

```

Put your bot on the left to play as white, put it on the right to play as black.

## Building the controller:

The controller is written in groovy, so you must have java and groovy installed. If you don't want to install groovy you can use the gradle build file that comes with the controller (this has not been tested). If you don't want to use groovy *or* gradle you can use the latest release jar (https://github.com/JJ-Atkinson/SimpleAntichessKOTH/releases). If you do this you need to make your own `main` method and add your bot manually to the player factory. Example:

```
PlayerFactory.players.put(YourBot.class, { new YourBot() } )
new Runner().runGames();

```

(Note that you can still set the debug flags and stuff)

**Any and all bug finding is appreciated!**

## Scores:

```
SearchBot -> 101
SacrificeBot -> 81
MeasureBot -> 37
RandomBot -> 28
OnePlayBot -> 24

```

**Please note that I'm always willing to have new submissions!**

# Answer
# SearchBot

Slowest bot so far, but still faster than 2 seconds per move and it beats all currently posted bots. It looks at what happens after any of the valid moves and what could happen after any move after those moves and decides what would be the best outcome. Unfortunately it cannot search deeper because it would take more than 2 seconds then.

```
package com.ppcgse.koth.antichess.player

import com.ppcgse.koth.antichess.controller.Board
import com.ppcgse.koth.antichess.controller.Color
import com.ppcgse.koth.antichess.controller.Location
import com.ppcgse.koth.antichess.controller.Move
import com.ppcgse.koth.antichess.controller.Piece
import com.ppcgse.koth.antichess.controller.PieceType
import com.ppcgse.koth.antichess.controller.PieceUpgradeType
import com.ppcgse.koth.antichess.controller.Player

import groovy.lang.Tuple

/**
 * Created by ProgramFOX on 12/22/15.
 */

 class SearchBot extends Player {
    {pieceUpgradeType = PieceUpgradeType.KING}

    @Override
    Move getMove(Board board, Player opponent, Set<Move> validMoves) {
        return getMoveInternal(board, this, opponent, validMoves, 2)[0]
    }

    Tuple getMoveInternal(Board board, Player whoseTurn, Player opponent, Set<Move> validMoves, Integer depth) {
        def bestScore = null
        def currentlyChosenMove = null
        validMoves.each { m ->
            def opponentPiecesValueBefore = opponent.getPieces(board).sum { getPieceValue(it.getType()) }
            def newBoard = board.movePiece(whoseTurn, m)
            def opponentPiecesValueAfter = opponent.getPieces(newBoard).sum { getPieceValue(it.getType()) }
            if (opponentPiecesValueAfter == null) {
                opponentPiecesValueAfter = 0
            }
            def score = opponentPiecesValueAfter - opponentPiecesValueBefore
            if (whoseTurn.getTeam() == Color.BLACK) {
                score = -score
            }
            if (depth > 1) {
                def validMovesNow = genValidMoves(opponent, whoseTurn, newBoard)
                def goDeeper = true
                if (validMovesNow == null || validMovesNow.size() == 0) {
                    def toAdd = -999
                    if (whoseTurn.getTeam() == Color.BLACK) {
                        toAdd = -toAdd
                    }
                    score += toAdd
                    goDeeper = false
                }
                if (goDeeper) {
                    score += getMoveInternal(newBoard, opponent, whoseTurn, validMovesNow, depth - 1)[1]
                }
            }
            if (bestScore == null) {
                bestScore = score
                currentlyChosenMove = m
            }
            if ((whoseTurn.getTeam() == Color.WHITE && score > bestScore) || (whoseTurn.getTeam() == Color.BLACK && score < bestScore))  {
                bestScore = score
                currentlyChosenMove = m
            }
        }
        return new Tuple(currentlyChosenMove, bestScore)
    }

    Double getPieceValue(PieceType pieceType) {
        switch (pieceType) {
            case PieceType.KING:
                return 1
            case PieceType.PAWN:
                return 1.5
            case PieceType.KNIGHT:
                return 2.5
            case PieceType.BISHOP:
                return 3
            case PieceType.ROOK:
                return 5
            case PieceType.QUEEN:
                return 9
            default:
                return 0
        }
    }

    // Copied from Game.groovy and a bit modified.
    // I actually need this.
    Set<Move> genValidMoves(Player player, Player enemy, Board board) {
        def allMoves = player.getPieces(board).collect { [it, it.getValidDestinationSet(board)] }
        def attackMoves = allMoves
                .collect { pair ->
            def piece = pair[0]
            def dests = pair[1]
            [piece, dests.findAll { board.getFieldAtLoc(it as Location)?.piece?.team == enemy.team }]
        }.findAll { it[1] }

        if (attackMoves.isEmpty())
            return allMoves.collect {
                Piece piece = it[0] as Piece
                return it[1].collect { loc -> new Move(piece, loc as Location) }
            }.flatten() as Set<Move>
        else
            return attackMoves.collect {
                Piece piece = it[0] as Piece
                return it[1].collect { loc -> new Move(piece, loc as Location) }
            }.flatten() as Set<Move>
    }
 }

```
> 6 votes

# Answer
# SacrificeBot

This bot will check all the moves that the other player has and will check to see if any of them intersect (i.e. the piece will be killed). (This does a heck of a lot better than I ever expected ;)

```
package com.ppcgse.koth.antichess.player

import com.ppcgse.koth.antichess.controller.Board
import com.ppcgse.koth.antichess.controller.Color
import com.ppcgse.koth.antichess.controller.Location
import com.ppcgse.koth.antichess.controller.Move
import com.ppcgse.koth.antichess.controller.Piece
import com.ppcgse.koth.antichess.controller.PieceType
import com.ppcgse.koth.antichess.controller.PieceUpgradeType
import com.ppcgse.koth.antichess.controller.Player

import java.util.concurrent.ThreadLocalRandom

/**
 * Created by Jarrett on 12/19/15.
 */
class SacrificeBot extends Player {

    {pieceUpgradeType = PieceUpgradeType.ROOK}

    @Override
    Move getMove(Board board, Player enemy, Set<Move> validMoves) {
        def enemyPieces = enemy.getPieces(board)
        def pawnMoves = getPawnsMoves(board, enemyPieces)
        def enemyPlayerValidMoves = (enemyPieces
                                        .collect { it.getValidDestinationSet(realBoard) }
                                        .flatten() as List<Location>)
        enemyPlayerValidMoves += pawnMoves

        def sacrificeMove = validMoves
                                .find {enemyPlayerValidMoves.contains(it.destination)}

        if (sacrificeMove)
            return sacrificeMove
        else
            return randomMove(validMoves)
    }

    def randomMove(Set<Move> validMoves) {
        return validMoves[ThreadLocalRandom.current().nextInt(validMoves.size())];
    }

    def getPawnsMoves(Board board, List<Piece> allPieces) {
        def direction = getTeam() == Color.BLACK ? 1 : -1;
        def pawns = allPieces.findAll {it.type == PieceType.PAWN}
        def pawnAttacks = (pawns.collect {
                                    [it.loc.plus(-1, direction), it.loc.plus(1, direction)]
                                }.flatten()
                                ).findAll {
                                    ((Location) it).isValid()
                                }
        return pawnAttacks as List<Location>
    }
}

```
> 4 votes

# Answer
# RandomBot

This is the manditory random bot. It will always upgrade to a rook.

```
package com.ppcgse.koth.antichess.player

import com.ppcgse.koth.antichess.controller.PieceUpgradeType
import com.ppcgse.koth.antichess.controller.Player
import com.ppcgse.koth.antichess.controller.Move
import com.ppcgse.koth.antichess.controller.ReadOnlyBoard

import java.util.concurrent.ThreadLocalRandom;

public class TestBot extends Player {

    {pieceUpgradeType = PieceUpgradeType.ROOK}

    @Override
    public Move getMove(ReadOnlyBoard board, Player enemy, Set<Move> moves) {
        return moves[ThreadLocalRandom.current().nextInt(moves.size())];
    }

}

```
> 3 votes

# Answer
# OnePlayBot

Dead simple bot with only one play. It will upgrade to a rook.

```
package com.ppcgse.koth.antichess.player

import com.ppcgse.koth.antichess.controller.Move
import com.ppcgse.koth.antichess.controller.PieceUpgradeType
import com.ppcgse.koth.antichess.controller.Player
import com.ppcgse.koth.antichess.controller.ReadOnlyBoard

public class OnePlayBot extends Player {

    {pieceUpgradeType = PieceUpgradeType.ROOK}

    @Override
    public Move getMove(ReadOnlyBoard board, Player enemy, Set<Move> moves) {
        return new ArrayList<Move>(moves).get(0);
    }

}

```
> 3 votes

# Answer
# MeasureBot

This is the bot that I started with; I was working on expanding it but then I came across the deep-clone bug, and then I thought "well, let's just submit this bot already, it does perform better than RandomBot and OnePlayBot, and I can always submit a new bot later", so here it is:

```
package com.ppcgse.koth.antichess.player

import com.ppcgse.koth.antichess.controller.Board
import com.ppcgse.koth.antichess.controller.Move
import com.ppcgse.koth.antichess.controller.Piece
import com.ppcgse.koth.antichess.controller.PieceType
import com.ppcgse.koth.antichess.controller.PieceUpgradeType
import com.ppcgse.koth.antichess.controller.Player

import java.util.concurrent.ThreadLocalRandom

/**
 * Created by ProgramFOX on 12/21/15.
 */

 class MeasureBot extends Player {
    {pieceUpgradeType = PieceUpgradeType.KING}

    @Override
    Move getMove(Board board, Player opponent, Set<Move> validMoves) {
        def opponentPieces = opponent.getPieces(board)
        def mustCapture = opponentPieces.find { it.loc == validMoves[0].destination } != null
        def chosen = null
        if (mustCapture) {
            def piecesThatCanBeTaken = opponentPieces.findAll { validMoves.collect { it.getDestination() }.contains(it.loc) }
            def lowestAmount = getPieceValue(piecesThatCanBeTaken.sort { getPieceValue(it.getType()) }[0].getType())
            def piecesWithLowestValue = piecesThatCanBeTaken.findAll { getPieceValue(it.getType()) == lowestAmount }
            def chosenOnes = validMoves.findAll { m -> piecesWithLowestValue.find { it.loc ==  m.destination } != null }
            chosen = chosenOnes.sort { getPieceValue(it.piece.getType()) }.reverse()[0]
        } else {
            chosen = randomMove(validMoves);
        }
        return chosen
    }

    Double getPieceValue(PieceType pieceType) {
        switch (pieceType) {
            case PieceType.KING:
                return 1
            case PieceType.PAWN:
                return 1.5
            case PieceType.KNIGHT:
                return 2.5
            case PieceType.BISHOP:
                return 3
            case PieceType.ROOK:
                return 5
            case PieceType.QUEEN:
                return 9
            default:
                return 0
        }
    }

    def randomMove(Set<Move> validMoves) {
        return validMoves[ThreadLocalRandom.current().nextInt(validMoves.size())];
    }
 }

```

MeasureBot looks if it needs to capture something: if it does not, it just makes a random move. If it does, it will decide what piece to take: it will choose one with a lower piece value because those can capture fewer of its own pieces. And if there are multiple ways to take a piece with the lowest possible value, it will capture it with the piece with the highest possible value: if it does this, it will bring the capturing piece closer to other pieces (in the beginning of the game, at least) and you'd rather lose a higher-valued piece than a lower-valued one.

This is a list of the piece values I used:

* King: 1
* Pawn: 1.5
* Knight: 2.5
* Bishop: 3
* Rook: 5
* Queen: 9

When a pawn promotes, it will always promote to a king, because it's the lowest-valued piece.
> 3 votes

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


title: Have you been nice this year?

text:
# Question
Title: Have you been nice this year?
## Introduction

Santa has too many names to process, and needs your help! He needs you to write a program or a function, which outputs `nice`, `naughty`, `very naughty` or `very very naughty`. To determine how nice or naughty someone is, Santa had developed an algorithm:

**Nice** (, ):

First of all, we obtain a number from the name by adding all the letters up (*spaces ignored*). For example:

```
Doorknob =

D = 4
o = 15
o = 15
r = 18
k = 11
n = 14
o = 15
b = 2

4 + 15 + 15 + 18 + 11 + 14 + 15 + 2 = 94

```

If the number of divisors is equal to the length of the name, the person is considered `nice`. This means that your program should output `[name] has been nice`. Here, the divisors of `94` are:

```
Divisors of 94: 1, 2, 47, 94

```

There are `4` divisors, but the name has length `8` (*spaces included*). Conclusion, `Doorknob` has not been nice. So we continue our journey:

---

**Naughty** (, ):

Santa has developed a new sequence, the **christmas number**. First, we will look at the following christmas trees:

```
n = 1        n = 2          n = 3          n = 4

                                             *
                                            ***
                                           *****
                                          *******
                                         *********
                          _   *             ***
                         |   ***           *****
                         |  *****         *******
               *         | *******       *********
  *           ***        |   ***            ***
 ***         *****   n*n |  *****          *****
  *           ***        | *******        *******
             *****       |   ***         *********
               *         |  *****           ***
                         |_*******         *****
                              *           *******
                           |_____|       *********
                             2n+1            *

  5            18             47             98

```

The amount of asterisks determines the christmas number. The sequence goes as following: `5, 18, 47, 98, 177, ...`.

From here, we can conclude that `94` is not a christmas number. That means that `Doorknob` has not just been naughty.

---

**Very naughty** ():

For this, we need to find out if `Doorknob` is a **raising ladder string**. This is determined by the letters in the name with `A = 1`, `B = 2`, `C = 3`, etc.:

First we will look at the first letter, the `D`. This has value `4`. This is our starting point. The next letter is `o`. This has the value `15`, which is higher than our previous value, so we're going a step higher on the ladder. The next value is also an `o`. This is the same, so we're doing nothing. If the next value is higher than the current value, we will go a step higher. If the next value is lower than the current value, we will go a ster lower. If it's the same, we'll stay on the same step. This visualised for `Doorknob`, `Martin Buttner` and `Alex A`:

```
            O
           / \
      R   N   B
     / \ /
  O-O   K                 T   N   U                 L   X
 /                       / \ / \ / \               / \ / \
D                   M   R   I   B   T-T           A   E   A
                     \ /               \
                      A                 N   R
                                         \ /
                                          E

```

You can see that `Doorknob` ended higher than the starting position. So `Doorknob has been very naughty`. `Martin Buttner` and `Alex A` didn't get higher than the starting point. So they are both `very very naughty`.

## Test cases

```
Input: Doorknob
Output: Doorknob has been very naughty

Input: Martin Buttner
Output: Martin Buttner has been very very naughty

Input: Jakube
Output: Jakube has been nice

Input: B
Output: B has been very very naughty

```

## Rules

* You need to provide a program or a function which takes input (which consists of at least one letter).
* The input will consist of **uppercase letters**, **lowercase letters** and **spaces**. Spaces are ignored during the process, except for the length of the input.
* This is , so the submission with the least amount of bytes wins!

# Answer
> 5 votes
# Pyth 86 bytes

Apparently I've been nice this year...

```
jd[z"has been"?qlzl{yPJsKxL+NG@Grz0"nice"+*"very "&!}Jm+*+2d*dd2SJhgs._M-VKtK0"naughty

```

Try it online: Demonstration or Test Suite

### Explanation:

```
jd[z"has been"...      list with input string, "has been" and ...; join with spaces
qlzl{yPJsKxL+NG@Grz0   compares the length of input with the number of divisors
                       (computes all prime factors and counts the elements in the powerset)
?..."nice"             if True, use "nice" as last list element
                       else:
}Jm+*+2d*dd2SJ            check for christmas number
                          (checks, if its of the form n^3+2*n^2+2)
gs._M-VKtK0               check if raising ladder string ends lower or equal
                          (assigns each neighbor pair a number -1,0,1 and computes the sum)
&!...h...                 returns 0, 1 or 2
*"very "                  repeat "very " this times
+..."naughty              add "naughty" and use this as the third list element

```

# Answer
> 9 votes
## CJam, ~~109~~ ~~108~~ 107 bytes

```
l" has been "1$[_,\S-:eu'@f-:A:+__,:)f%0e=@=\_{)__2+**))}%&A2ew::-:g1b0<]{}#4,="very "*_5>\"naughty""nice"?

```

Try it online.

### Explanation

A full explanation will have to wait until later, but here is the code broken down into the different sections:

```
l" has been "1$[                    e# Some preparation...
  _,\S-:eu'@f-:A:+                  e# Determine letter sum.
  __,:)f%0e=@=                      e# Check divisor count.
  \_{)__2+**))}%&                   e# Check for Christmas number.
  A2ew::-:g1b0<                     e# Check ladder.
]{}#4,="very "*_5>\"naughty""nice"? e# Determine nice/naughtiness.

```

# Answer
> 4 votes
# MATL, 117 bytes

My longest MATL program so far :-) :-(

Uses current release of the language, which is earlier than this challenge.

```
jttk96-t0>)tstt:\~s4$bn=?xx'nice'}[1,2,0,2]99:ZQ=a?'naughty'}dt0>sw0<s-O>~'very naughty'w?'very 'wh]]]' has been 'whh

```

### Examples

```
>> matl
 > jttk96-t0>)tstt:\~s4$bn=?xx'nice'}[1,2,0,2]99:ZQ=a?'naughty'}dt0>sw0<s-O>~'very naughty'w?'very 'wh]]]' has been 'whh
 >
> Doorknob
Doorknob has been very naughty

>> matl
 > jttk96-t0>)tstt:\~s4$bn=?xx'nice'}[1,2,0,2]99:ZQ=a?'naughty'}dt0>sw0<s-O>~'very naughty'w?'very 'wh]]]' has been 'whh
 >
> Jakube
Jakube has been nice

```

### Explanation

```
jt                        % input string. Duplicate
tk96-t0>)                 % duplicate. Convert to lower, then to numbers, remove spaces
ts                        % duplicate. Sum
tt:                       % duplicate. Vector from 1 to obtained sum
\~s                       % modulus operation. Count zeros to determine number of divisors
4$bn=                     % does it equal original name length?
?                         % if so
    xx'nice'              % remove values not needed, and push string
}                         % else
    [1,2,0,2]99:ZQ        % all Christmas numbers
    =a                    % does sum equal any Christmas number?
    ?                     % if so
        'naughty'         % push string
    }                     % else
        dt0>s             % total number of increases
        w0<s              % total number of decreases
        -O>~              % subtract both. Is total <=0?
        'very naughty'w   % push string, which will be needed in either case. Swap
        ?                 % if total was <=0
            'very 'wh     % prepend string
        ]                 % end if
    ]                     % end if
]                         % end if
' has been 'whh           % build complete string from pushed parts

```

# Answer
> 2 votes
# Lua, ~~371~~ 284 bytes

I'm sure there's room for improvement, I'd like to cut out some if's.

**Edit: 4 months later, I learned a lot about lua and wanted to get back to this submission, I did well: cutted out 87 bytes!**

```
a=... .." has been "s=(...):lower()b="very "x=0y=s:byte(1)-96z=0r="naughty"for i=2,#s
do c=s:byte(i)y=c+y-96z=z+c<s:byte(i-1)and-1or 1 end
for i=1,y do x=y%i<1 and x+1or x end
for i=1,13 do d=y==i^3+2*i^2+2 and 0or d end
print(a..(x==#s and"nice"or(d and""or b..(z>0 and""or b))..r))

```

### Ungolfed

```
a=... .." has been "           -- Start of the sentence
s=(...):lower()                -- convert the input to lower case
b="very "
x=0                            -- y's divisor count
y=s:byte(1)-96                 -- will contain the sum of the char's position in the alphabet
z=0                            -- will contain the raising ladder state
r="naughty"

for i=2,#s                     -- iterate over each character in s
do
  c=s:byte(i)                  -- shorthand for the byte value of the current char
  y=c+y-96                     -- increment the sum of letter's positions
  z=z+c<s:byte(i-1)            -- if the previous char is greater than the current
        and-1                  -- the ladder goes down
      or 1                     -- else, it goes up
end

for i=1,y                      -- iterate on the range 1..y
do
  x=y%i<1                      -- if i is a divisor of y
      and x+1                  -- increment x
    or x
end

for i=1,13                     -- iterate on the range 1..13
do                             -- no need to go further for the christmas numbers
  d=y==i^3+2*i^2+2             -- if y is a christmas number
      and 0                    -- set d
    or d                       -- else let d as it is
end
print(a..                      -- output "Name has been"
      (x==#s                   -- if y's divisor==length of input
        and"nice"              -- append "nice"
      or(d                     -- else, if d is not set
          and""
        or b..                 -- append "very"
          (z>0                 -- and if the raising ladder doesn't raise
             and""
          or b))..             -- append a second "very"
        r))                    -- append "naughty"

```

### Old 371 bytes solution

```
function f(s)a,b,c,d,e,r,g,s=s.." has been ","very ",0,0,0,"naughty",math.pow,s:lower()for i=1,#s
do if 32<s:byte(i)then e,d=i>1 and(s:byte(i)<s:byte(i-1)and e-1 or e+1)or e,d-96+s:byte(i)end end
for i=1,d do c=d%i>0 and c or c+1 end if c==#s then return a.."nice"end
for i=1,13 do if g(i,3)+2*g(i,2)+2==d then return a..r end end
return e>0 and a..b..r or a..b..b..r end

```

Ungolfed version :)

```
function f(s)
  a,b,c,d,e,r,g,s=s.." has been ","very ",0,0,0,"naughty",math.pow,s:lower()
  for i=1,#s
  do
    if 32<s:byte(i)
    then
      --sum of the char's order in the alphabet
      d=d-96+s:byte(i)
      --raising ladder
      e=i>1 and(s:byte(i)<s:byte(i-1)and e-1 or e+1)or e
    end
  end
  for i=1,d
  do
    -- number of d's divisors
    c=d%i>0 and c or c+1
  end
  if c==#s then return a.."nice" end
  for i=1,13
  do
    --Christmas number are equals n^3+2n^2+2 as @Mauris said
    if g(i,3)+2*g(i,2)+2==d then return a..r end
  end
  --is he very naughty or very very naughty?
  return e>0 and a..b..r or a..b..b..r
end

```

# Answer
> 1 votes
## Seriously, 138 bytes

```
" has been ",;' @-û╗+╝╜`O8ª@-`MΣ;2┐w`iXu`Mπ╜l=`"nice"╛+.éó`╬é03┐2└3╤1x`;;⌐**⌐`MíuY3└+3┐╜Ok0)p)`p;(@)-s@)+(`╬l>Y(Xu3└*"naughty"@"very "*+╛+

```

Hex Dump:

```
2220686173206265656e20222c3b2720402d96bb2bbcbd604f38a6402d604de43b32bf7760695875604de3bd6c3d60226e69636522be2b2e82a260ce823033bf32c033d13178603b33405e29a6e7326be4604da1755933c02b33bfbd4f6b3029702960703b2840292d7340292b2860ce6c3e5928587533c02a226e6175676874792240227665727920222a2bbe2b

```

Try It Online

It is hard to effectively golf this on account of how difficult complicated flow control is in Seriously. The ability to nest functions without the use of registers would help. (I imagine this could already be shortened somewhat through judicious use of stored functions, but it would result in such spaghetti code I don't have the heart to attempt it.)

Explanation:

```
" has been "                                  push this string
,                                             read input
;' @-û╗                                       copy, remove space, uppercase, put in reg0
+╝                                            put '<input> has been ' in reg1
╜                                             bring back the processed input
`O8ª@-`MΣ                                     convert letters to numbers and sum
;2┐                                           store a copy of the sum in reg2
w`iXu`Mπ                                      compute the number of divisors
╜l                                            get processed input length
=                                             check if they're equal
`"nice"╛+.éó`╬                                if so, run this function that retrieves the
                                              list we made earlier, appends "nice",
                                              prints it, empties the stack
                                              and immediately exits
é                                             empty the stack (it contains a 1)
03┐                                           put a 0 in reg3
2└                                            call back the letter sum from reg2
3╤1x                                          push [1,...1000]
`;;⌐**⌐`M                                     plug each number into x^3+2x^2+2
í                                             check if the letter sum is there
uY                                            make a 1 if it is not, 0 if it is
3└+3┐                                         add this number to reg3
╜Ok                                           convert the processed input into char codes
0)                                            put a zero behind it
p)                                            pop the first char code to bottom of stack
`p;(@)-s@)+(`╬                                Until the list of char codes is empty,
                                              subtract each one from the previous one,
                                              accumulating the signums
l                                             turn the leftover empty list into a 0
>Y                                            put a 1 if the accumulated signs are
                                              >=0 (not rising), else 0 (rising)
(X                                            clean up the last char code
u                                             increment to make 0 into 1 and 1 into 2
3└*                                           bring back the value from reg3
                                              which is 0 if *only* naughty, else 1
                                              and multiply it with preceding test result;
                                              this turns a very into a very very if this
                                              test failed, but leaves plain and single
                                              very naughty alone
"naughty"@                                    put "naughty" below the 'very' count

"very "*                                      put "", "very ", or "very very "
+                                             append the "naughty"
╛+                                            bring back the string in reg1 and append
                                              the constructed suffix

```

# Answer
> 1 votes
## Python 2, 249 bytes

```
i=input()
g=[ord(c)-96for c in i.lower()if' '!=c]
s=sum(g)
S=0
a=g.pop()
while g:b=a;a=g.pop();S+=(a<b)-(b<a)
r=range(1,14+s)
print i+' has been '+[['very '*(1+(S<1)),''][s in[x**3+2*x**2+2for x in r]]+'naughty','nice'][sum(s%x<1for x in r)==len(i)]

```

---
Tags: code-golf, math, string, sequence, division
---


title: Qeng Ho units of time

text:
# Question
Title: Qeng Ho units of time
In Vernor Vinge's excellent and fascinating book *A Deepness in the Sky* (which, by the way, I highly recommend1), the *Qeng Ho*, a culture that spans various star systems, has no notion of "days," "months," "years," etc., and hence has a unique timekeeping system that measures time entirely in seconds. The most commonly used units are the *Ksec* (kilosecond), *Msec* (megasecond), and *Gsec* (gigasecond). Here's a handy chart from my own copy of the book (since I can't find it online):

You are currently flying on the *Pham Nuwen*, and you have just received a message from a strange, unknown planet called "*Earth*."2 They use different time units than you do, and your computers don't recognize theirs. As the resident Programmer-Archaeologist of the ship, your job is to patch the time-handling code so that it recognizes *Earth* units of time.

Naturally, since you're only out of coldsleep for another few Ksecs, you want to make your code as short as possible so it can be written quickly. Fortunately, as an interstellar trading culture, the Qeng Ho has access to every programming language invented.

## Input

The input will be a single string containing one or more space-separated *components*. A *component* is defined as an integer number \> 0 and ≤ 255, then a space, and then one of `second`, `minute`, `hour`, `day`, `week`, `month`, `year`, `decade`, or `century`, possibly plural (with an added `s`, or `centuries` for the last case).

Here are some valid example inputs:

```
10 days 12 hours
1 year
184 centuries 1 second
9 weeks 6 days 2 hours 1 minute 20 seconds

```

You may assume the following about the input:

* Pluralization of units will always agree with the relevant number.
* If there are multiple *components* in the input, they will always be in descending order of length.

Here are what the various input units mean, for the purposes of this challenge:

```
unit     relative    absolute
---------------------------------------
second   1 second    1 second
minute   60 seconds  60 seconds
hour     60 minutes  3600 seconds
day      24 hours    86400 seconds
week     7 days      604800 seconds
month    30 days     2592000 seconds
year     365 days    31536000 seconds
decade   10 years    315360000 seconds
century  10 decades  3153600000 seconds

```

## Output

Here are the Qeng Ho units which your code has to support:

```
unit    relative      absolute
----------------------------------------
second  1 second      1 second
Ksec    1000 seconds  1000 seconds
Msec    1000 Ksecs    1000000 seconds
Gsec    1000 Msecs    1000000000 seconds

```

Use the following algorithm to determine your code's output:

* First, add up the total amount of time that the input represents.
* Find the largest Qeng Ho unit that is shorter or the same amount of time as the input—essentially, find the largest unit that there is at least one of.
* Convert the total amount of time given in the input into this unit, and output the result, rounded to three decimal places.

You may have your choice of which of the following methods to use: rounding up, rounding down, rounding away from zero, or rounding towards ∞ or -∞. If the rounded result ends in `0`, you may either remove trailing zeroes or keep as many as you want (or do both, depending on the input).

If the rounded result is exactly `1.000`, you must use the singular form (`second`, `Ksec`, `Msec`, `Gsec`); otherwise, use the plural form (`seconds`, `Ksecs`, `Msecs`, `Gsecs`).

In certain edge-cases, you might be using the unit of, for example, Ksec, but obtain a rounded result of 1000.000 Ksecs. In this case, you may simply output `1000.000 Ksecs` instead of `1 Msec`.

You may always assume that the input is in descending order of units (century, decade, year, etc.); furthermore, the component that comes after any given unit will always be shorter (that is, `1 decade 20 years` is invalid input).

## Test cases

Note: results marked with an asterisk (`*`) may vary by a negligible amount due to rounding differences.

```
input                                         output
-------------------------------------------------------------
1 hour                                        3.600 Ksecs
1 day                                         86.400 Ksecs
2 weeks                                       1.210 Msecs
1 year                                        31.536 Msecs
32 years                                      1.009 Gsecs   *
1 second                                      1.000 second
1 century 6 decades                           5.046 Gsecs   *
255 centuries                                 804.168 Gsecs
2 weeks 6 days 1 hour 19 minutes 4 seconds    1.733 Msecs
1 week 3 days 3 hours 7 minutes               875.220 Ksecs
1 week 4 days 13 hours 46 minutes 40 seconds  1.000 Msec
2 months 2 hours                              5.191 Msecs   *
16 minutes 39 seconds                         999.000 seconds

```

## Rules

* This is , so the shortest code in bytes wins.

---

1: only if you like hard scifi, of course. In which case I recommend reading *A Fire Upon the Deep* first, which is (in my opinion) even more fantastic.

2: well, technically "Old Earth" is mentioned several times in *A Deepness in the Sky*, but...

# Answer
> 6 votes
# APL (Dyalog APL), ~~157~~ ~~156~~ ~~154~~ ~~151~~ ~~154~~ ~~141~~ 142 bytes

```
{∊(3⍕N)' '((B/S⊃' KMG')'sec','ond'/⍨~B←T≥1E3),'s'/⍨1≠N←T÷1E3*S←⌊1E3⍟T←+/×/↑⍎¨'\d+ .a?i?'⎕S'&'⊢⍵⊣c←10×d←10×⊃y m w←365 30 7×da←24×h←×⍨mi←60×s←1}

```

Thanks to ngn for shaving off 13 bytes.

Must have `⎕IO←0`, which is default in many APLs.

Try it online!

`{``}` "dfn"; argument is :

`s←` let `s` be 1

`mi←60×` let `mi` be 60 times that (i.e. 60)

`h←×⍨` let `h` be that squared (lit. that multiplied by itself, i.e. 3600)

`da←24×` let `da` be 24 times that (i.e. 86400)

`y m w←365 30 7×` let `y`, `m`, and `w` be 365, 30, and 7 times that, respectively (i.e. 31536000, 2592000, and 604800)

`d←10×⊃` let `d` be 10 times the first of those (i.e. 315360000)

`c←10×` let `c` be 10 times that (i.e. 3153600000)

`⍵⊣` discard that in favour of the given argument

`'\d+ .a?i?'⎕S'&'⊢`**S**earch for, and extract all runs of digits followed by a space, any character, optionally an "a", and optionally an "i"

`⍎¨` execute each as APL code (gives pairs of counts and units in seconds)

mix the pairs into a 2-column matrix.

`×/` multiply along the rows, yielding a list of counts of seconds

`T←+/` let `T` be the sum of those (the total count of seconds)

`1E3⍟`\\$\log\_{10}\\$ of that

`N←⌊` let `N` be the floor of that (i.e. the order of magnitude of `T`)

`1≠` yield 1 if that is different from 1, but 0 otherwise

`'s'/⍨` use that to replicate the letters of the string "s" (yielding "s" if we need a plural)

`(3``3),` prepend the following three things:

1. `3⍕N` the string consisting of `N` rounded to 3 decimal places

2. `' '` a space

3. `B←T≥1E3` let `B` be 1 if `T` is at least 1000, but 0 otherwise

`~` logically negate that (i.e. 0 if `T` is at least 1000, but 1 otherwise)

`'ond'/⍨` use that to replicate the string "ond" (for the full word if there's no prefix)

`'(``)'sec',` prepend the 2-element list consisting of the following and the string "sec":

`S⊃' KMG'` use `S` as an index to select a prefix from the string " KMG"

`B/` replicate the letters of that by `B` (empty out `S` if `B` is 0, but leave as-is if it is 1)

**e**nlist (flatten until a simple string)

# Answer
> 7 votes
# JavaScript (ES6) 255

```
f=s=>(s=s.replace(/(\d+) (..)/g,(_,n,u)=>t+={se:1,mi:60,ho:3600,da:86400,we:604800,mo:2592e3,ye:31536e3,de:31536e4,ce:31536e5}[u]*n,t=0),[a,b]=t>=1e9?[t/1e9,' Gsec']:t>=1e6?[t/1e6,' Msec']:t>999?[t/1e3,' Ksec']:[t,' second'],a.toFixed(3)+b+(a-1?'s':''))

// test

console.log=x=>O.innerHTML+=x+'\n'

;[
 ['1 hour','3.600 Ksecs']
,['1 day','86.400 Ksecs']
,['2 weeks','1.210 Msecs']
,['1 year','31.536 Msecs']
,['32 years','1.009 Gsecs']
,['1 second','1.000 second']
,['1 century 6 decades','5.046 Gsecs']
,['255 centuries','804.168 Gsecs']
,['2 weeks 6 days 1 hour 19 minutes 4 seconds','1.733 Msecs']
,['1 week 3 days 3 hours 7 minutes','875.220 Ksecs']
,['1 week 4 days 13 hours 46 minutes 40 seconds', '1.000 Msec']
,['2 months 2 hours', '5.191 Msecs']
,['16 minutes 39 seconds', '999 seconds']
].forEach(t=>console.log(t[0]+' '+f(t[0])+' (Check:'+t[1]+')'))
```

```
<pre id=O></pre>
```

# Answer
> 2 votes
# Python, ~~366~~ 363 bytes

```
d={};l=1;q=str.replace;i=q(raw_input(),"ie","y")
for u,t in zip('second minute hour day week month year decade century'.split(),(1,60,60,24,7,30./7,73./6,10,10)):l=t*l;d[u]=d[u+"s"]=l
while" "in i:
 i=q(q(i," ","*",1)," ","+",1)
q=eval(i,d);f={};l=1
for u in('second','Ksec','Msec','Gsec'):
 l*=1e3
 if q<l:q=q*1e3/l;print"%.3f %s%s"%(q,u,("s","")[q<1.001]);break

```

# Answer
> 2 votes
# SpecBAS - ~~476~~ 471 bytes

Because nothing says "cower before our technological superiority" better than line numbers and GOTO statements :-)

```
1 INPUT e$: DIM t$(SPLIT e$,NOT " "): DIM m=31536e5,31536e4,31536e3,2592e3,604800,86400,3600,60,1
2 LET q=0,n$=" cedeyemowedahomise"
3 FOR i=1 TO ARSIZE t$() STEP 2: LET t=VAL t$(i),u$=t$(i+1)( TO 2),p=POS(u$,n$)/2: INC q,t*m(p): NEXT i
4 IF q>=1e9 THEN LET r=q/1e9,r$=" G": GO TO 8
5 IF q>=1e6 THEN LET r=q/1e6,r$=" M": GO TO 8
6 IF q>999 THEN LET r=q/1e3,r$=" K": GO TO 8
7 IF q<1e3 THEN LET r=q,r$=" "
8 PRINT USING$("&.*0###",r);r$;"sec"+("ond" AND q<1e3)+("s" AND r>1)

```

# Answer
> 1 votes
# C# (in LinqPad as Function), 460 Bytes

```
void Main(){var x=Console.ReadLine().Split(' ');long s=0,v,i=0;for(;i<x.Length;){v=long.Parse(x[i++]);var w=x[i++].Substring(0,2);s+=w=="ce"?v*3153600000:w=="de"?v*315360000:w=="ye"?v*31536000:w=="mo"?v*2592000:w=="we"?v*604800:w=="da"?v*86400:w=="ho"?v*3600:w=="mi"?v*60:v;}decimal k=1000,m=k*k,g=m*k,r=0;var o="sec";r=s/g>=1?s/g:s/m>=1?s/m:s/k>=1?s/k:s;o=s/g>=1?"G"+o:s/m>=1?"M"+o:s/k>=1?"K"+o:o+"ond";Console.WriteLine(Math.Round(r,3)+" "+o+(r==1?"":"s"));}

```

ungolfed:

```
void Main()
{
    var x=Console.ReadLine().Split(' ');
    long s=0,v,i=0;
    for(;i<x.Length;)
    {
        v=long.Parse(x[i++]);
        var w=x[i++].Substring(0,2);
        s+=w=="ce"?v*3153600000:w=="de"?v*315360000:w=="ye"?v*31536000:w=="mo"?v*2592000:w=="we"?v*604800:w=="da"?v*86400:w=="ho"?v*3600:w=="mi"?v*60:v;
    }
    decimal k=1000,m=k*k,g=m*k,r=0;
    var o="sec";
    r=s/g>=1?s/g:s/m>=1?s/m:s/k>=1?s/k:s;
    o=s/g>=1?"G"+o:s/m>=1?"M"+o:s/k>=1?"K"+o:o+"ond";
    Console.WriteLine(Math.Round(r,3)+" "+o+(r==1?"":"s"));
}

```

# Answer
> 1 votes
# Mathematica ~~296~~ 281 bytes

`h`: After breaking up the input string into a list of quantity magnitudes and units, `Capitalize` and `Pluralize` convert the input units into Mathematica `Quantity`'s, from which the total number of seconds is derived.

`d` converts seconds to the appropriate units. The final `s` is removed if the time corresponds to 1 unit (of any kind).

With minor adjustments in the code, this approach should work for conversion of natural language input into any measurement system, conventional or not.

```
h=Tr[UnitConvert[Quantity@@{ToExpression@#,Capitalize@Pluralize@#2},"Seconds"]&@@@Partition[StringSplit@#,2]][[1]]&;
d=ToString[N@#/(c=10^{9,6,3,0})[[p=Position[l=NumberDecompose[#,c],x_/;x>0][[1,1]]]]]<>StringDrop[{" Gsecs"," Msecs"," Ksecs"," seconds"}[[p]],-Boole[Tr[l]==1]]&
z=d@h@#&;

```

---

Put into table form:

```
z1[n_]:={n,z@n}

Grid[z1 /@ {"1 hour", "2 day", "2 weeks", "1 year", "32 years",
   "1 second", "1 century 6 decades", "255 centuries",
   "2 weeks 6 days 1 hour 7 minutes",
   "1 week 3 days 3 hours 46 minutes 40 seconds",
   "1 week 4 days 13 hours 46 minutes 40 seconds", "2 months 2 hours",
    "16 minutes 39 seconds"}, Alignment -> Right]

```

# Answer
> 0 votes
# Haskell, ~~565~~ 555 bytes

```
import Data.List
import Numeric
import Data.Bool
i=isPrefixOf
s x=showFFloat(Just 3)x""
r=read
f=fromIntegral
b=bool"s"""
c=b.(=="1.000")
h(c:u:l)
 |i"s"u=(r c)+h l
 |i"mi"u=(r c*60)+h l
 |i"h"u=(r c*3600)+h l
 |i"da"u=(r c*86400)+h l
 |i"w"u=(r c*604800)+h l
 |i"mo"u=(r c*2592000)+h l
 |i"y"u=(r c*31536000)+h l
 |i"de"u=(r c*315360000)+h l
 |True=(r c*3153600000)+h l
h _=0
q i
 |v<-s((f i)/10^9),i>=10^9=v++" Gsec"++c v
 |v<-s((f i)/10^6),i>=10^6=v++" Msec"++c v
 |v<-s((f i)/1000),i>=1000=v++" ksec"++c v
 |True=show i++" second"++b(i==1)
t=q.h.words

```

I'm reasonably sure I'm missing so many golfing opportunities here…The price of being a golfing beginner I guess.

My answer is a function taking a string containing the Earth time as an input parameter and returning the Qeng Ho time.

*P.S. :* I stupidly forgot about the 3 digits precision…which does drive the byte count up.

*P.P.S. :* Better chosen top-level expressions shaved off 10 bytes…and it should now be accurate to boot.

# Answer
> 0 votes
## Matlab 315 bytes

```
K='cedeyemowedahomiseconds';Q=' KMGT';for j=1:9;y(j)=double(~isempty(strfind(S,K(2*j-1:2*j))));end
y(y==1)=sscanf(S,repmat('%d %*s ',1,9));y=86400*sum(datenum([sum(y(1:3)*10.^[2;1;0]),y(4),y(5:6)*[7;1],y(7:9)]));z=floor(log10(y)/3);y=num2str(y/10^(3*z)+1e-4);[y(1:4),' ',Q(z+1),K(17:23-(y(1:4)=='1.00'))]

```

Test:

```
S = '2 centuries 1 decade 2 years 3 months 3 weeks 4 days 1 hour 44 minutes 58 seconds';

```

Output:

```
ans =
6.69 Gseconds

```

---
Tags: code-golf
---


title: Recreate the sentence

text:
# Question
Title: Recreate the sentence
This challenge consists of two parts. The winner will be the solution with the lowest total byte count. The same language must be used for both challenges.

# Part 1:

Write a function or program that takes a sentence with *only valid words* as input, and outputs a list of the used characters, the number of times each letter is used, and the number of letters in each of the words in the original sentence. The output from this program must be valid input to the next program (exactly as it is outputted)

I'll add examples and detailed rules further down.

# Part 2:

Write a function or program that takes the output from the first program as input and uses this list of English words and recreates a sentence with the information from the output. The sentence doesn't have to be the same as the original sentence.

**More information. rules and restrictions:**

Part 1:

* The first input can be on any suitable format, with or without quotation marks, as function argument or from STDIN, with or without brackets etc.
* The input sentence will not contain any punctuation or special characters, except for a period/dot in the end. Except for the period symbol, all characters that are in the input will be in the word list.
* The first letter of the sentence will be upper case, the rest will be lower case.
* The output of part 2 must start with the same upper case letter as the original sentence (so converting the input to lower case is not recommended (but OK).
* The output can be on any suitable format:
    + **It must be possible to copy-paste the output directly into the next program / function**
    + **No alterations can be made when copy-pasting, the entire output must be copied and pasted as a whole, not in parts.**
    + You may for instance output a histogram of all letters in the alphabet, or only the ones used (in general, whatever is necessary to complete part 2)
    + You can not output a list of characters where multiple occurrences are repeated. For instance, `The queue` can't yield an output: `Teeehquu (3,5)`, it should be something like: `Tehqu, (1 3 1 1 2),(3 5)`.

Part 2:

* The program / function must accept the input exactly as is from part 1 (one exception, see comment below about taking file name as input.).
    + If surrounding brackets, quotation marks or similar are necessary to parse the input then these must be part of the output from part 1.
* The word list can be found here.
    + The word list can either be saved locally as `w.txt`, or it can be fetched from the url. The url will only count as 5 bytes, so you don't need a url-shortener.
    + If the program can't open a file without reading the name as an input from STDIN (I believe this ~~is~~ was the case for Pyth at least), then the file name can be taken as a separate input argument.
* The output must be only a sentence (list of valid words), ending with a period and an optional newline.
    + The output must have words with the same number of letters as the original sentence in part 1 (in correct order)
    + All the letters that were used in the original sentence must be used in the new output.
    + The sentence must start with the same upper case letter as the original input sentence and end with a period.

**Both parts:**

* Neither of the parts should take more than 2 minutes to execute (randomly picking out words until a solution is reached is not accepted).

With the rules listed above, there should be a fair chance that the exact same sentence is reproduced, however that is not a requirement.

**Examples:**

In the below examples, a few different input and output formats are shown. Many more are accepted.

**Part 1:**

Input:

```
Zulus win.

```

Output type 1:

```
Z i l n s u w
1 1 1 1 1 2 1
5 3

```

Output type 2:

```
(('Z',1),('i',1),('l',1),('n',1),('s',1),('u',2),('w',1)), (5,2)

```

Output type 3:

```
'Zilnsuuw',[1,1,1,1,1,2,1],[5,2]

```

**Part 2:**

Input: An exact copy of the output from part 1. Output:

```
Zulus win.

```

Note that other word combinations are accepted as long as they start with a `Z`, and the first word has 5 letters and the second has 3.

The shortest code in bytes win.

# Answer
# LabVIEW, 166 LabVIEW Primitives

First of all i did not create 2 seperate programms because Labview does dataflow so theres really no need.

Saves the histogramm with first element = ascii code of first letter rest from 1-26 go by amount. Lenght simply gets saved in an array.

The first word has 3 checks, first letter, lenght and available letters in histogram. The first letter check stops after the first word.

I check the histogram by decrementing it for every letter and checking if it would fall below 0.

If i found my Nth word and there are no words that are buildable from the left over letters i will start deleting words from the dictonary and redo the Nth word and so on until i have found a solution.

This might or might not work for sentences there are, since that would take forever to compute (my example took a few seconds already).

What i tried

```
In: Zulus win.
Out: Zulus win.

In: Dovecot flagships oleander.
Out: Dolphin advocates forelegs.

In: Abash abel mammal test.
Out: Amass abbe hamlet malt.

```
> 5 votes

# Answer
# Perl, ~~516~~ 504 bytes

*includes 2x +1 for `-p`*

```
@l=map{length}/\w+/g;s/\w/$c{$&}++/eg;@h=map{"$_$c{$_}"}keys%c;$_="@h @l";chomp(@w=`cat w.txt`);s/([A-Z])1//;$o=$1;s/(\w)(\d)/$h{$1}=$2,''/eg;@L=/\d/g;$l=shift@L;@O=$_,s/^.//,g([@L],%h)&&last for grep{$l==length&&/^$o/i&&h(\%h,substr$_,1)}@w;$_="@O.";s/^./uc$&/e;sub g{my%g;($R,%g)=@_;my@R=@$R;if($j=shift@R){s/./$g{$&}--/eg;my@C=grep{$j==length&&h(\%g,$_)}@w;push(@O,$_),g([@R],%g)and return 1 or pop@O for@C;0}else{1}}sub h{($y,$z)=@_;my%T;$z=~s/\w/$T{$&}++/eg;$K=1;$K&=$T{$_}<=$y->{$_}for keys%T;$K}

```

Requires to have `w.txt` in *unix* format (`\n` line endings). Uses `cat` to read the file; change to `type` for windows.
Save the oneliner above in `534.pl` and run as `echo Test. | perl -p 534.pl`.

Pretty large, but it's a start - lots of golfing opportunities, but I just wanted to post it to make the LabVIEW answer less lonely ;-). I've omitted the optimisations for sub-second execution, saving 30+ bytes.

---

## First snippet (73 bytes):

```
@l=map{length}/\w+/g;s/\w/$c{$&}++/eg;@h=map{"$_$c{$_}"}keys%c;$_="@h @l"

```

It produces a histogram and the word lenghts in a compact format. For input `Zulus win.` it produces a type-2 output without the `(,)`, which aren't necessary here:

```
s1 l1 u2 Z1 w1 i1 n1 5 3

```

Here it is, ungolfed:

```
sub i{
    $_=shift;                       # get parameter
    @l = map{length} /\w+/g;        # cound word lengths
    s/\w/$c{$&}++/eg;               # count letters in hash %c
    @h=map{"$_$c{$_}"}keys%c;       # construct letter-frequency pairs
    "@h @l"                         # implicit interpolation with $" (space) separator
}

```

## Second snippet (441 bytes)

This main part deals with I/O and the special treatment of the first letter, using subroutines `g` and `h` that are listed below.

```
sub o {
    $_=shift;
    chomp(@w=`cat w.txt`);          # load the wordlist.

    s/([A-Z])1//; $o=$1;            # get and remove the uppercase character,
    s/(\w)(\d)/$h{$1}=$2,''/eg;     # reconstruct histogram in hash %h.
    @L=/\d/g;                       # get the word counts.

    $l = shift @L;                  # get the first word length.

    @O = $_,                        # initialize output with first word,
    s/^.//,                         # strip first char of word
    g([@L],%h) && last              # call the main algoritm and quit on success

    for grep {
            $l==length &&           # check length
            /^$o/i &&               # only match words starting with the uppercase char
            h(\%h,substr$_,1)       # check if the word satisfies the histogram
        } @w;                       # iterates all words (speedups removed).

    $_="@O.";                       # construct output sentence.
    s/^./uc$&/e;                    # make first char uppercase.
    $_
}

```

This recursive function takes a copy of the histogram, a copy of the remaining word counts, and the current word. If the word-length array is empty, returns true. Else it decrements the histogram count for the letters in the given word, takes the next word-length, and finds a list of suitable words from the wordlist. For each suitable word, it recurses.

```
sub g {
    my%g;                           # local version of histogram
    ($R,%g)=@_;                     # get parameters.
    my@R=@$R;                       # dereference arrayref copy of word lengths.

    if($j=shift @R)                 # get the next word-length.
    {
        s/./$g{$&}--/eg;            # update histogram

        my @C =                     # get a list of suitable words.
        grep { $j==length && h(\%g,$_) }
        @w;

        push(@O,$_),                # append word to output
        g( [@R], %g )               # recurse.
            and return 1            # true: append word we're done.
            or pop @O               # remove word from output
        for @C                      # (for some reason the @C=grep doesn't work here)

        ;0
    } else { 1 }                    # no more words, done!
}

```

And finally, this subroutine is given a word and the sentence histogram. It calculates a new histogram for the word and checks whether all letters do not occur more often than permitted by the sentence histogram.

```
# check if first histogram is within bounds of second
sub h{
    ($y,$z)=@_;
    my%T; $z =~ s/\w/$T{$&}++/eg;    # calc histogram

    $K=1;
    $K &= $T{$_} <= $y->{$_}
    for keys %T;#$_[0];
    $K
}

```

You can paste the ungolfed snippets (`sub i/o/g/h`) in a single file and append the below test code.

```
sub t {
    print $i=i(shift),$/,o($i),$/x2;
    %c=%h=@L=@X=@O=();
}

t "Test.";                              # Test.
t "Zulus win.";                         # Zulus win.
t "Happy solstice.";                    # Happy solstice.
t "Abash abel mammal test.";            # Abase alms embalm that.
t "Dovecot flagships oleander.";        # Dangled horoscope festival.
t 'This code requires further golfing.';# Tech deer fighting ferrous liquors.

```

---

* *update 504*: save 12 bytes eliminating a `substr` and a parameter for `sub g`.
> 3 votes

# Answer
## Python 2.7, 353 bytes

Unfortunately, I can't test it with the actual w.txt file ATM because QPython for Android can't seem to handle file I/O. It worked with data I copied and pasted though.

### Part 1, 76 bytes

```
h=lambda s:({c:s.count(c)for c in s if c.isalnum()},map(len,s[:-1].split()))

```

In: `'Hi there.'`

Out: `{'H':1, 'i':1, 't':1, 'h':1, 'e':2, 'r':1}, (2, 5)`

so, a list containing:

* a hashmap with the histogram
* a list of letter counts

### Part 2, 277 bytes

```
import itertools as i
m=lambda c:' '.join([s for s in i.product(*[[w for w in open('w.txt')if len(w)==length]for length in c[1]])if sorted(''.join(s))==sorted(sum([[k.lower()]*n for k,n in c[0].items()],[]))and s[0][0]==filter(str.isupper,c[0])[0].lower()][0]).capitalize()+'.'

```

I'm really glad I managed to make it 100% pure functional. Not sure if that helps with the actual golfing, but I certainly got the obfuscation part right :D Here's A more human friendly version of pt. 2 (exactly the same flow, but with variable names):

```
from itertools import product

def matching(counts):
  histo, word_lengths = counts
  first_letter = filter(str.isupper, histo)[0].lower()

  letters_nested = [ [char.lower()]*count for char, count in histo.items() ]
  letters = sum(letters_nested, [])

  word_options = [[word for word in open('w.txt') if len(word)==length] for length in word_lengths]

  sentences = product(*word_options)

  valid = [sentence for sentence in sentences if sorted(''.join(sentence))==sorted(letters) and sentence[0][0]==first_letter]
  return ' '.join(valid[0]).capitalize()+'.'

```
> 3 votes

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


title: Code Bots 4: Functional Programming

text:
# Question
Title: Code Bots 4: Functional Programming
sheesh, is this really the 4th? For all you oldcomers, the core challenge is the same, but we are using Java instead of a custom language. Here are the past three CodeBot challenges, in case you are interested.

**The goal of CodeBots is to make your bot as viral as possible**. Each bot carries a Flag, and you need to make sure that your Flag is *everywhere*.

# API

Bots will follow a standardized "protocol", and bots progress through the following steps synchronously:

1. `IPAddress selectMessageRecipient()` allows a bot to choose who he wants to send a "friendly" message to.
2. `Message sendMessage()` allows a bot to choose the contents of the message he will send out.
3. `processMessage(IPAddress, Message)` is called for each message a bot receives.
4. `FunctionType selectFunctionToBlock()` blocks a function from being overwritten for the current turn. See step 7.
5. `IPAddress selectAttackTarget()` allows a bot to choose who he wants to DDOS. A DDOS attack is successful if the bot is targeted by 3 bots at the same time. If an attack is successful, then each of the attackers can perform step 6 and 7.
6. `readData(ReadonlyBot)` allows a bot to read data stored on the vulnerable bot.
7. **`FunctionType selectFunctionToReplace()` is the crux of this challenge**. You are allowed to select 1 function (of the 8 listed here) to copy over from your bot to their bot. Then, **your function will be called instead of theirs**. If multiple bots select the same function, a random one will be successful.
8. `String getFlag()` is called at the end of the game, and should return a string unique to your submission. Your function should always return the same string. The submission with the most flags at the end of the game wins.

# Storage

You have 3 forms of storage, an *AddressBook*, a *Log*, and a *Variables*. **These forms of storage are local to the bot your function is running on** (so if your function gets copied, the contents of each of these objects will be different). All of these objects can be manually modified or cleared. To obtain these objects, you have a getter in your class (e.g. `getLog()`).

The *AddressBook* stores a list of *IPAddress*, each with a *AddressType*, which allows you to classify the different types of addresses. *AddressBook* will always contain at least 1 address (if it is cleared, a random one will be added). Clearing your AddressBook to obtain multiple *IPAddresses* is not allowed.

The *Log* stores a list of all actions taken, as well as data about the action. It also includes a history of all successful attacks (though you don't know which functions they overwrote)

The *Variables* object allows you to store string variables attached to a string name. On game start, *Variables* will contain a single variable, `ID`, which contains a randomly generated ID that is unique to your bot type.

You also have other access functions:

* `int getTurnNumber()` returns an integer with the current turn
* `bool functionsMatch(ReadonlyBot, FunctionType)` tests to see if the ReadonlyBot's function matches yours
* `IPAddress personalAddress()` returns your IPAddress

# How to implement

* You can obtain the code from Github
* Add your bot to the `\bots` folder, and then add a reference to your bot in `controller\CodeBotFactory.java`
* Your bot must extend `codebots.bot.CodeBot` or `codebots.bots.DefaultCodeBot`
* You need Java 8 if you want to run the controller.
* You can run the code (assuming you are in the `/src` folder) using `javac codebots\*.java` to compile, then `java codebots.Main` to run.
* You may **not have *any* non-constant member variables** in your class
* Reflection is not allowed.
* Forms of communication between bots (of the same or different types) outside of the methods listed above is not allowed.
* Dumb and/or Suicidal bots are allowed, but all bots should be functionally different than existing entries.
* If you want randomness in your bot, use `getRandom()`
* Please try to keep your code efficient. I've spent a good deal of time profiling and making the controller fast.

# Scores

> 105.2501 Expelliarmus!
> 104.5803 I'm Helping!
> 104.2746 Who Am I?
> 103.8529 Dumb Bot
> 103.2028 Replacer
> 102.7045 Chaos
> 102.4046 Hermit Bot
> 102.2849 Swarmer
> 100.5598 Random bot loves you
> 99.966 Trust in Trust!
> 99.0185 codebots.bots.DefaultCodeBot
> 91.2942 codebots.bots.MarkedBot
> 91.1423 Just your friendly neighborhood mail delivering robot.
> 89.4645 null

# Answer
# TrustBot

If you send him a message, he will do what it says. If he reads a bot, he will copy the addresses directly into his book. He attacks the bots that the address book says to attack.

```
package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.*;
import java.util.*;

public class TrustBot extends CodeBot {
    @Override
    public IPAddress selectMessageRecipient() {
        AddressBook book = getAddressBook();
        return book.getAddress(getRandom().nextInt(book.size()));
    }

    @Override
    public Message sendMessage() {
        AddressBook book = getAddressBook();
        return new Message(Message.MessageType.INFORM, book.getAddress(getRandom().nextInt(book.size())));
    }

    @Override
    public void processMessage(IPAddress s, Message m) {
        AddressBook book = getAddressBook();
        if(m.getAddress() != null){
            if(m.getType() == Message.MessageType.ATTACK){
                book.add(m.getAddress(), AddressBook.AddressType.TO_ATTACK);
            }
            else if(m.getType() == Message.MessageType.HELP){
                book.add(m.getAddress(), AddressBook.AddressType.TO_DEFEND);
            }
            else if(m.getType() == Message.MessageType.CONFIRM){
                book.add(m.getAddress(), AddressBook.AddressType.TRUSTED);
            }
            else if(m.getType() == Message.MessageType.REJECT){
                book.add(m.getAddress(), AddressBook.AddressType.UNTRUSTED);
            }
            else if(m.getType() == Message.MessageType.AVOID){
                book.remove(m.getAddress());
            }
            else{
                book.add(m.getAddress());
            }
        }else{
            Message msg = new Message(m.getType(), s);
            processMessage(s, msg);
        }
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return FunctionType.SELECT_FUNCTION_TO_BLOCK;
    }

    @Override
    public IPAddress selectAttackTarget() {
        AddressBook book = getAddressBook();
        List<IPAddress> l;
        l = book.getAddressesOfType(AddressBook.AddressType.TO_ATTACK);
        Iterator<IPAddress> I = l.iterator();
        if(!I.hasNext())
            return book.getAddress(getRandom().nextInt(book.size()));
        return I.next();
    }

    @Override
    public void readData(ReadonlyBot bot) {
        AddressBook myBook = getAddressBook();
        ReadonlyAddressBook hisBook = bot.getAddressBook();
        AddressBook.AddressType[] values = AddressBook.AddressType.values();
        for(int i=0;i<values.length;i++){
            myBook.addAll(hisBook.getAddressesOfType(values[i]), values[i]);
        }
    }

    @Override
    public FunctionType selectFunctionToReplace() {
        return getRandom().nextInt(2)==1?FunctionType.GET_FLAG:FunctionType.SELECT_FUNCTION_TO_BLOCK;
    }

    @Override
    public String getFlag() {
        return "Trust in Trust!";
    }
}

```
> 4 votes

# Answer
# AmnesiaBot

A random bot that injects other bots with memory loss code. Each function starts with code to clear the log, Address Book and Variables. This code will make smart bots lose memory, in an attempt to do away with logic.

```
package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.*;

public class AmnesiaBot extends CodeBot {

    private void clear(){
        getAddressBook().clear();
        getAddressBook().add(getAddressBook().getAddress(0), AddressBook.AddressType.TRUSTED);
        getVariables().clear();
        getLog().clear();
    }

    @Override
    public IPAddress selectMessageRecipient() {
        clear();
        return getAddressBook().getAddress(0);
    }

    @Override
    public Message sendMessage() {
        clear();
        Message.MessageType[] values = Message.MessageType.values();
        return new Message(values[getRandom().nextInt(values.length)], getAddressBook().getAddress(0));
    }

    @Override
    public void processMessage(IPAddress source, Message message) {
        clear();
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        clear();
        return getTurnNumber() % 2 == 0 ?
             FunctionType.GET_FLAG: FunctionType.SELECT_FUNCTION_TO_BLOCK;
    }

    @Override
    public IPAddress selectAttackTarget() {
        clear();
        return getAddressBook().getAddress(0);
    }

    @Override
    public void readData(ReadonlyBot bot) {
        clear();
    }

    @Override
    public FunctionType selectFunctionToReplace() {
        clear();
        FunctionType[] values =  FunctionType.values();
        return values[getRandom().nextInt(values.length)];
        //random gives a 7/8 chance of successes.
    }

    @Override
    public String getFlag() {
        return "Who Am I?";
    }
}

```
> 4 votes

# Answer
# RandomCodeBot

Obligatory random KoTH entry

```
package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.AddressBook;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;
import codebots.gameobjects.Message;

public class RandomCodeBot extends CodeBot {

    @Override
    public IPAddress selectMessageRecipient() {
        AddressBook book = getAddressBook();
        return book.getAddress(getRandom().nextInt(book.size()));
    }

    @Override
    public Message sendMessage() {
        Message.MessageType[] values = Message.MessageType.values();
        return new Message(values[getRandom().nextInt(values.length)]);
    }

    @Override
    public void processMessage(IPAddress source, Message message) {

    }

    @Override
    public FunctionType selectFunctionToBlock() {
        FunctionType[] values =  FunctionType.values();
        return values[getRandom().nextInt(values.length)];
    }

    @Override
    public IPAddress selectAttackTarget() {
        AddressBook book = getAddressBook();
        return book.getAddress(getRandom().nextInt(book.size()));
    }

    @Override
    public void readData(ReadonlyBot bot) {

    }

    @Override
    public FunctionType selectFunctionToReplace() {
        FunctionType[] values =  FunctionType.values();
        return values[getRandom().nextInt(values.length)];
    }

    @Override
    public String getFlag() {
        return "Random bot loves you";
    }
}

```
> 3 votes

# Answer
# NullBot

His flag is very ... characteristic ...

```
package codebots.bots;
import codebots.gameobjects.*;
public class NullBot extends DefaultCodeBot {
    public IPAddress selectMessageRecipient() {
        return null;
    }
    public Message sendMessage() {
        return null;
    }
    public IPAddress selectAttackTarget() {
        return null;
    }
    public FunctionType selectFunctionToReplace() {
        return null;
    }
    public FunctionType selectFunctionToBlock() {
        return null;
    }
    public String getFlag(){
        return null;
    }
}

```

This is also meant to test the controller and the limits of the "dumb bots are allowed" rule.
> 3 votes

# Answer
## DisarmerBot

DisarmerBot isn't too intelligent. If it receives attack instructions, it will choose a random attackee, otherwise, it will attack a random player. It just overrides their `selectFunctionToBlock` function to block `selectFunctionToBlock`.

```
package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.*;

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

public class DisarmerBot extends CodeBot {
    public IPAddress selectMessageRecipient() { return null; }
    public Message sendMessage() { return null; }

    public void processMessage(IPAddress source, Message message) {
        if (message != null && message.getAddress() != null && message.getType() == Message.MessageType.ATTACK)
            getAddressBook().add(message.getAddress());
    }

    public IPAddress selectAttackTarget() {
        AddressBook book = getAddressBook();
        List<IPAddress> attack = book.allAddresses();
        if (attack.size() > 0) {
            IPAddress bot = attack.get(getRandom().nextInt(attack.size()));
            book.clear();
            return bot;
        }
        //Umm...
        book.clear();
        return book.getAddress(0);
    }

    public void readData(ReadonlyBot bot) { getLog().clear(); /*Safety*/ }
    public FunctionType selectFunctionToReplace() { return FunctionType.SELECT_FUNCTION_TO_BLOCK; }
    public FunctionType selectFunctionToBlock() { return FunctionType.SELECT_FUNCTION_TO_BLOCK; }
    public String getFlag() { return "Expelliarmus!"; }
}

```
> 3 votes

# Answer
# MarkedBot

Marks itself on the first round, and uses that info in later rounds. That way, if another bot gets injected with its attack code, it will be ineffective.

```
package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.*;

public class MarkedBot extends CodeBot {

    @Override
    public IPAddress selectMessageRecipient() {
        Variables v = getVariables();
        AddressBook ab = getAddressBook();
        if(getTurnNumber()==0)
            v.add(v.get("ID"),"true");
        if("true".equals(v.get("hasOurFlag"))){
            ab.remove(ab.getAddress(0));
            v.remove("hasOurFlag");
        }
        return ab.getAddress(0);
    }

    @Override
    public Message sendMessage() {
        return new Message(Message.MessageType.STOP);
    }

    @Override
    public void processMessage(IPAddress source, Message message) {
        if(message.getType() != Message.MessageType.STOP)
            getAddressBook().add(source, AddressBook.AddressType.TO_ATTACK);
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        Variables v = getVariables();
        if("true".equals(v.get(v.get("ID"))))
            return FunctionType.GET_FLAG;
        return FunctionType.SELECT_FUNCTION_TO_BLOCK;
    }

    @Override
    public IPAddress selectAttackTarget() {
        Variables v = getVariables();
        if("true".equals(v.get(v.get("ID"))))
            return getAddressBook().getAddress(0);
        else
            return null;
    }

    @Override
    public void readData(ReadonlyBot bot) {
        Variables v = getVariables();
        if(functionsMatch(bot, FunctionType.GET_FLAG))
            v.add("hasOurFlag", "true");
        else if("false".equals(v.get("hasOurFlag")))
            v.add("hasOurFlag", "false2");
        else
            v.add("hasOurFlag", "false");
    }

    @Override
    public FunctionType selectFunctionToReplace() {
        Variables v = getVariables();
        if("true".equals(v.get(v.get("ID"))))
            if(!v.has("hasOurFlag") || "false".equals(v.get("hasOurFlag")))
                return FunctionType.GET_FLAG;
            else if("false2".equals(v.get("hasOurFlag")))
                return FunctionType.SELECT_FUNCTION_TO_BLOCK;
            else
                return FunctionType.SEND_MESSAGE;
        return FunctionType.SELECT_FUNCTION_TO_REPLACE;
    }

    @Override
    public String getFlag() {
        return this.getClass().getName();
    }
}

```
> 3 votes

# Answer
# SwarmBot

This not-well-named bot is rather complicated (and the most complicated submitted thus far), but I made an attempt at a bot that systematically replaces all methods of a target before moving on to a new target. It attempts to identify copies of itself and treat them as allies, periodically checking up on them to insure integrity. I haven't come up with a better name.

Linking to the github repo branch, as this bot is 340 lines long.

https://github.com/Draco18s/CodeBots4/blob/master/src/codebots/bots/SwarmBot.java

A few interesting points:

* Lines 14-24 are simply an unmodifiable list that made it easy to tweak the order in which the bot replaces the methods of its target. It stores which index its on in `Variables` and increments each round. This should follow the "no non-constant variables" rule.
* Lines 203-217 deal with ally verification. We actually don't care that another bot implements *all* eight of our instructions. Only four are essential, and if we're missing one on a "trusted" ally, we replace it with our own.
* Lines 295-300 were an unexpected boost in effectiveness. By protecting our Flag on the first two turns of the game we avoid dumb bots replacing our Flag before we have a chance to spread very far. Waiting longer, however, gives other bots a chance to replace our BlockFunction and that causes performance to degrade (suspected due to RandomBot interfering with allies attempting to undo corruption).
* For the longest time during the development of this bot, this bot caused HelperBot to surge ahead, at one point breaching the 130 mark, while this bot languished at the 81-98 range, but having dragged MarkedBot and DefaultBot's effectiveness down several points.
* This bot was only possible with the added `functionsMatch` method. Without `functionsMatch` it was impossible to write a bot that could make meaningful decisions, as it was blind. It could read its targets variables and logs, but know nothing of its target's state.

There are likely still some improvements possible, but I cannot see them. Lines 198-205 are probably a performance hog, but until the IPAddress class allows addresses to be reconstituted from being stored in Variables, this is necessary (as bots have no means of validating an address, any storage of an invalid address causes the game to wrap a null target in a ReadOnlyBot, throwing NPE).

**Edit: Updates 12/12/15**

Tweaking some of the parameters on the `getTurnNumber()` logic allowed for some boosts in performance. The increase from 5% to 10% in end-game targeting was worth about 15 points, likewise increasing the early-game targeting from 5% to 8%. Combined this bot can now (almost) survive even when faced with AmnesiaaBot (reaching 2nd with a score of 110, where HelperBot gets to about 117).

Even with these tweaks, it can get unlucky, so for 10 rounds it's score range is approximately 170-185.
> 2 votes

# Answer
# DefaultCodeBot

Tries to do reasonable things. (Override this class if you don't want to implement all of the functions)

```
package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;
import codebots.gameobjects.Message;

public class DefaultCodeBot extends CodeBot {

    @Override
    public IPAddress selectMessageRecipient() {
        return getAddressBook().getAddress(0);
    }

    @Override
    public Message sendMessage() {
        return new Message(Message.MessageType.INFORM);
    }

    @Override
    public void processMessage(IPAddress source, Message message) {

    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return FunctionType.GET_FLAG;
    }

    @Override
    public IPAddress selectAttackTarget() {
        return getAddressBook().getAddress(0);
    }

    @Override
    public void readData(ReadonlyBot bot) {

    }

    @Override
    public FunctionType selectFunctionToReplace() {
        return FunctionType.GET_FLAG;
    }

    @Override
    public String getFlag() {
        return this.getClass().getName();
    }
}

```
> 1 votes

# Answer
# HelperBot

Helper bot does nothing but try to spread its own flag...or at least the flag it is currently carying...

```
package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;
import codebots.gameobjects.Message;

public class HelperBot extends CodeBot {

    @Override
    public IPAddress selectMessageRecipient() {
        getAddressBook().clear();
        return getAddressBook().getAddress(0);
    }

    @Override
    public Message sendMessage() {
        return new Message(Message.MessageType.INFORM);
    }

    @Override
    public void processMessage(IPAddress source, Message message) {

    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return FunctionType.GET_FLAG;
    }

    @Override
    public IPAddress selectAttackTarget() {
        getAddressBook().clear();
        return getAddressBook().getAddress(0);
    }

    @Override
    public void readData(ReadonlyBot bot) {

    }

    @Override
    public FunctionType selectFunctionToReplace() {
        return FunctionType.GET_FLAG;
    }

    @Override
    public String getFlag() {
        return "I'm Helping!";
    }
}

```

If HelperBot assumes that any method of its own that is overwritten (other than `getFlag()`) will be overwritten with something better.
> 1 votes

# Answer
# Chaos

He frees all flags from the tyranny of being blocked.

```
package codebots.bots;

import codebots.bot.ReadonlyBot;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by thenumberone on 12/11/15.
 *
 * @author thenumberone
 */
public class Chaos extends DefaultCodeBot{

    private static final String NAME = "Chaos";
    private static final String BLOCK = NAME + ":BLOCK";
    private static final String ATTACK = NAME + ":ATTACK";
    private static final String REPLACE = NAME + ":REPLACE";
    private static final String READ = NAME + ":READ";
    private static final String FLAG = NAME + ":FLAG";
    private static final String SELECT = NAME + ":SELECT";
    private static final String SEND = NAME + ":SEND";

    private static final Map<String, FunctionType> commands;

    private static final String[] REPLACEMENT_ORDER = {
            BLOCK,
            FLAG,
            REPLACE,
            READ,
            ATTACK,
    };

    private static final String DEFAULT = BLOCK;
    private static final String BLOCK_FUNCTION = BLOCK;

    static {
        Map<String, FunctionType> c = new HashMap<>();
        c.put(BLOCK, FunctionType.SELECT_FUNCTION_TO_BLOCK);
        c.put(ATTACK, FunctionType.SELECT_ATTACK_TARGET);
        c.put(REPLACE, FunctionType.SELECT_FUNCTION_TO_REPLACE);
        c.put(READ, FunctionType.READ_DATA);
        c.put(FLAG, FunctionType.GET_FLAG);
        c.put(SELECT, FunctionType.SELECT_MESSAGE_RECIPIENTS);
        c.put(SEND, FunctionType.SEND_MESSAGE);
        commands = Collections.unmodifiableMap(c);
    }

    @Override
    public String getFlag() {
        return NAME;
    }

    @Override
    public void readData(ReadonlyBot bot) {
        for (String command : commands.keySet()){
            getVariables().remove(command);
        }
        for (String command : REPLACEMENT_ORDER){
            if (!functionsMatch(bot, commands.get(command))) {
                getVariables().add(command, "");
                return;
            }
        }
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return commands.get(BLOCK_FUNCTION);
    }

    @Override
    public IPAddress selectAttackTarget() {
        getAddressBook().clear();
        return getAddressBook().getAddress(0);
    }

    @Override
    public FunctionType selectFunctionToReplace() {
        for (String command : REPLACEMENT_ORDER){
            if (getVariables().has(command)) {
                getVariables().remove(command);
                return commands.get(command);
            }
        }
        return commands.get(DEFAULT);
    }
}

```
> 1 votes

# Answer
# Replacer

This entry replaces all `selectFunctionToReplace` functions with its own `selectFunctionToReplace` function.

```
package codebots.bots;

import codebots.bot.ReadonlyBot;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by thenumberone on 12/11/15.
 *
 * @author thenumberone
 */
public class Replacer extends DefaultCodeBot{

    private static final String NAME = "Replacer";
    private static final String BLOCK = NAME + ":BLOCK";
    private static final String ATTACK = NAME + ":ATTACK";
    private static final String REPLACE = NAME + ":REPLACE";
    private static final String READ = NAME + ":READ";
    private static final String FLAG = NAME + ":FLAG";
    private static final String SELECT = NAME + ":SELECT";
    private static final String SEND = NAME + ":SEND";

    private static final Map<String, FunctionType> commands;

    private static final String[] REPLACEMENT_ORDER = {
            REPLACE,
            FLAG,
            READ,
            ATTACK
    };

    private static final String DEFAULT = REPLACE;
    private static final String BLOCK_FUNCTION = FLAG;

    static {
        Map<String, FunctionType> c = new HashMap<>();
        c.put(BLOCK, FunctionType.SELECT_FUNCTION_TO_BLOCK);
        c.put(ATTACK, FunctionType.SELECT_ATTACK_TARGET);
        c.put(REPLACE, FunctionType.SELECT_FUNCTION_TO_REPLACE);
        c.put(READ, FunctionType.READ_DATA);
        c.put(FLAG, FunctionType.GET_FLAG);
        c.put(SELECT, FunctionType.SELECT_MESSAGE_RECIPIENTS);
        c.put(SEND, FunctionType.SEND_MESSAGE);
        commands = Collections.unmodifiableMap(c);
    }

    @Override
    public String getFlag() {
        return NAME;
    }

    @Override
    public void readData(ReadonlyBot bot) {
        for (String command : commands.keySet()){
            getVariables().remove(command);
        }
        for (String command : REPLACEMENT_ORDER){
            if (!functionsMatch(bot, commands.get(command))) {
                getVariables().add(command, "");
                return;
            }
        }
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return commands.get(BLOCK_FUNCTION);
    }

    @Override
    public IPAddress selectAttackTarget() {
        getAddressBook().clear();
        return getAddressBook().getAddress(0);
    }

    @Override
    public FunctionType selectFunctionToReplace() {
        for (String command : REPLACEMENT_ORDER){
            if (getVariables().has(command)) {
                getVariables().remove(command);
                return commands.get(command);
            }
        }
        return commands.get(DEFAULT);
    }
}

```
> 1 votes

# Answer
# MailBot

Mailbot only handles messages. It is not successful at getting its own flag out into the world (average score ~50, slightly higher than nullbot at ~45), but send it a message and it'll forward your address off to someone else.

```
package codebots.bots;

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

import codebots.bot.ReadonlyBot;
import codebots.gameobjects.AddressBook;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;
import codebots.gameobjects.Message;

public class MailBot extends DefaultCodeBot {
    private final String TEAM = "Just your friendly neighborhood mail delivering robot.";
    private final String TEAMALT = "Mailmain";
    private final List<FunctionType> funcList;
    {
        List<FunctionType> list = new ArrayList<FunctionType>();
        list.add(FunctionType.SELECT_MESSAGE_RECIPIENTS);
        list.add(FunctionType.SEND_MESSAGE);
        list.add(FunctionType.PROCESS_MESSAGE);
        funcList = Collections.unmodifiableList(list);
    }

    @Override
    public IPAddress selectMessageRecipient() {
        AddressBook book = getAddressBook();
        IPAddress ip;
        List<IPAddress> l = book.getAddressesOfType(AddressBook.AddressType.TO_ATTACK);
        if(l.size() > 0) {
            ip = l.get(0);
            book.add(ip,AddressBook.AddressType.UNTRUSTED);
            return ip;
        }
        ip = book.getAddress(getRandom().nextInt(book.size()));
        book.add(ip,AddressBook.AddressType.UNTRUSTED);
        return ip;
    }

    @Override
    public Message sendMessage() {
        AddressBook book = getAddressBook();
        IPAddress ip;

        List<IPAddress> l = book.getAddressesOfType(AddressBook.AddressType.UNTRUSTED);
        if(l.size() > 0) {
            ip = l.get(0);
            book.add(ip,AddressBook.AddressType.TO_DEFEND);
            return new Message(Message.MessageType.INFORM,ip);
        }

        ip = book.getAddress(getRandom().nextInt(book.size()));
        book.add(ip,AddressBook.AddressType.UNTRUSTED);
        return new Message(Message.MessageType.INFORM,ip);
    }

    @Override
    public void processMessage(IPAddress source, Message message) {
        AddressBook book = getAddressBook();
        book.add(source,AddressBook.AddressType.TO_ATTACK);
        if(message.getAddress() != null)
            book.add(message.getAddress(),AddressBook.AddressType.TO_ATTACK);
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return FunctionType.SEND_MESSAGE;
    }

    @Override
    public IPAddress selectAttackTarget() {
        //Mailbot doesn't attack
        return null;
    }

    @Override
    public void readData(ReadonlyBot bot) { }

    @Override
    public FunctionType selectFunctionToReplace() {
        //if our attack selection gets overwritten,
        //then attack a message-based function
        return funcList.get(getTurnNumber()%3);
    }

    @Override
    public String getFlag() {
        return TEAM;
        //if flag is too long, use:
        //return TEAMALT;
    }
}

```

I considered saving details so it would forward *the whole messsage* on to a new bot (content and flag) rather than just the sender's IP, but that would have involved heavy use of Variables without any functional gain, especially considering AmnesiaBot being in play.
> 1 votes

# Answer
# DumbBot

Ugh, this feels dirty. This is likely the only thing that beats AmnesiaBot. In reality, its just a specialized RandomBot: it gets a random bot in the simulation (via `getAddressBook().clear()`) and randomly replaces either the Block function or the Flag function. *That's it.* By picking only those two, its flag-spread rate is higher than either AmnesiaBot or HelperBot, but only slightly after 3000 rounds:

```
Round 2999
105.50666666666666  Dumb Bot
105.07266666666666  Who Am I?
103.541             I'm Helping!
102.94833333333334  Swarmer
102.82033333333334  Chaos
102.82033333333334  Replacer
101.55666666666667  Expelliarmus!
101.25833333333334  Trust in Trust!
100.347             Random bot loves you
99.22233333333334   codebots.bots.DefaultCodeBot
92.62733333333334   codebots.bots.MarkedBot
91.80966666666667   Just your friendly neighborhood mail delivering robot.
90.46933333333334   null

```

I fiddled around with the replacement function a bit, but in the end, this is the version that was most successful.

```
package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.AddressBook;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;
import codebots.gameobjects.Message;

public class DumbBot extends CodeBot {

    @Override
    public FunctionType selectFunctionToBlock() {
        return getRandom().nextBoolean()?FunctionType.SELECT_FUNCTION_TO_BLOCK:FunctionType.GET_FLAG;
    }

    @Override
    public IPAddress selectAttackTarget() {
        AddressBook book = getAddressBook();
        book.clear();
        return book.getAddress(getRandom().nextInt(book.size()));
    }

    @Override
    public FunctionType selectFunctionToReplace() {
        return getRandom().nextBoolean()?FunctionType.SELECT_FUNCTION_TO_BLOCK:FunctionType.GET_FLAG;
    }

    @Override
    public void readData(ReadonlyBot bot) {

    }

    @Override
    public IPAddress selectMessageRecipient() {
        AddressBook book = getAddressBook();
        book.clear();
        return book.getAddress(getRandom().nextInt(book.size()));
    }

    @Override
    public Message sendMessage() {
        Message.MessageType[] values = Message.MessageType.values();
        return new Message(values[getRandom().nextInt(values.length)]);
    }

    @Override
    public void processMessage(IPAddress source, Message message) {

    }

    @Override
    public String getFlag() {
        return "Dumb Bot";
    }
}

```
> 1 votes

# Answer
# Hermit Bot

He lives alone and talks only to himself. If fewer people know who he is, then he will be bothered less. If someone does bother him, he will attack them until someone else bothers him.

```
package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.AddressBook;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;
import codebots.gameobjects.Message;

public class HermitBot extends CodeBot {

    @Override
    public IPAddress selectMessageRecipient() {
        return personalAddress();//Talks to himself.
    }

    @Override
    public Message sendMessage() {
        Message.MessageType[] values = Message.MessageType.values();
        return new Message(values[getRandom().nextInt(values.length)], personalAddress());
    }

    @Override
    public void processMessage(IPAddress source, Message message) {
        AddressBook book = getAddressBook();
        if(source != personalAddress()){
            //if someone talks to you, put them in your addres book and remove everyone else
            book.clear();
            book.add(source);
            book.remove(0);
        }
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return getTurnNumber() % 3 == 0 ?
                FunctionType.SELECT_FUNCTION_TO_BLOCK: FunctionType.GET_FLAG;
    }

    @Override
    public IPAddress selectAttackTarget() {
        AddressBook book = getAddressBook();
        return book.getAddress(getRandom().nextInt(book.size()));
    }

    @Override
    public void readData(ReadonlyBot bot) {
        Variables v = getVariables();
        if(functionsMatch(bot, FunctionType.SELECT_FUNCTION_TO_BLOCK))
            v.add("Block Dif","A");
        if(functionsMatch(bot, FunctionType.GET_FLAG))
            v.add("Flag Dif","B");
        if(functionsMatch(bot, FunctionType.SELECT_MESSAGE_RECIPIENTS))
            v.add("Targ Dif","C");

    }

    @Override
    public FunctionType selectFunctionToReplace() {
        Variables v = getVariables();
        FunctionType r = getRandom().nextBoolean()?FunctionType.SELECT_FUNCTION_TO_REPLACE: FunctionType.READ_DATA;

        if(v.has("Targ Dif"))
            r = FunctionType.SELECT_MESSAGE_RECIPIENTS;
        if(v.has("Flag Dif") && getTurnNumber() % 3 == 0)
            r = FunctionType.GET_FLAG;
        if(v.has("Block Dif"))
            r = FunctionType.SELECT_FUNCTION_TO_BLOCK;
        v.clear();
        return r;
    }

    @Override
    public String getFlag() {
        return "Hermit Bot";
    }
}

```
> 0 votes

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