Task: Two bullet roulette


C++: #include <array>
#include <iomanip>
#include <iostream>
#include <random>
#include <sstream>

class Roulette {
private:
    std::array<bool, 6> cylinder;

    std::mt19937 gen;
    std::uniform_int_distribution<> distrib;

    int next_int() {
        return distrib(gen);
    }

    void rshift() {
        std::rotate(cylinder.begin(), cylinder.begin() + 1, cylinder.end());
    }

    void unload() {
        std::fill(cylinder.begin(), cylinder.end(), false);
    }

    void load() {
        while (cylinder[0]) {
            rshift();
        }
        cylinder[0] = true;
        rshift();
    }

    void spin() {
        int lim = next_int();
        for (int i = 1; i < lim; i++) {
            rshift();
        }
    }

    bool fire() {
        auto shot = cylinder[0];
        rshift();
        return shot;
    }

public:
    Roulette() {
        std::random_device rd;
        gen = std::mt19937(rd());
        distrib = std::uniform_int_distribution<>(1, 6);

        unload();
    }

    int method(const std::string &s) {
        unload();
        for (auto c : s) {
            switch (c) {
            case 'L':
                load();
                break;
            case 'S':
                spin();
                break;
            case 'F':
                if (fire()) {
                    return 1;
                }
                break;
            }
        }
        return 0;
    }
};

std::string mstring(const std::string &s) {
    std::stringstream ss;
    bool first = true;

    auto append = [&ss, &first](const std::string s) {
        if (first) {
            first = false;
        } else {
            ss << ", ";
        }
        ss << s;
    };

    for (auto c : s) {
        switch (c) {
        case 'L':
            append("load");
            break;
        case 'S':
            append("spin");
            break;
        case 'F':
            append("fire");
            break;
        }
    }

    return ss.str();
}

void test(const std::string &src) {
    const int tests = 100000;
    int sum = 0;

    Roulette r;
    for (int t = 0; t < tests; t++) {
        sum += r.method(src);
    }

    double pc = 100.0 * sum / tests;

    std::cout << std::left << std::setw(40) << mstring(src) << " produces " << pc << "% deaths.\n";
}

int main() {
    test("LSLSFSF");
    test("LSLSFF");
    test("LLSFSF");
    test("LLSFF");

    return 0;
}



Go: package main

import (
    "fmt"
    "math/rand"
    "strings"
    "time"
)

var cylinder = [6]bool{}

func rshift() {
    t := cylinder[5]
    for i := 4; i >= 0; i-- {
        cylinder[i+1] = cylinder[i]
    }
    cylinder[0] = t
}

func unload() {
    for i := 0; i < 6; i++ {
        cylinder[i] = false
    }
}

func load() {
    for cylinder[0] {
        rshift()
    }
    cylinder[0] = true
    rshift()
}

func spin() {
    var lim = 1 + rand.Intn(6)
    for i := 1; i < lim; i++ {
        rshift()
    }
}

func fire() bool {
    shot := cylinder[0]
    rshift()
    return shot
}

func method(s string) int {
    unload()
    for _, c := range s {
        switch c {
        case 'L':
            load()
        case 'S':
            spin()
        case 'F':
            if fire() {
                return 1
            }
        }
    }
    return 0
}

func mstring(s string) string {
    var l []string
    for _, c := range s {
        switch c {
        case 'L':
            l = append(l, "load")
        case 'S':
            l = append(l, "spin")
        case 'F':
            l = append(l, "fire")
        }
    }
    return strings.Join(l, ", ")
}

func main() {
    rand.Seed(time.Now().UnixNano())
    tests := 100000
    for _, m := range []string{"LSLSFSF", "LSLSFF", "LLSFSF", "LLSFF"} {
        sum := 0
        for t := 1; t <= tests; t++ {
            sum += method(m)
        }
        pc := float64(sum) * 100 / float64(tests)
        fmt.Printf("%-40s produces %6.3f%% deaths.\n", mstring(m), pc)
    }
}