オフラインリアルタイムどう書くE04 をビット演算で解いた・その２

解説はそのうち…。

- 問題はこちら: http://mtsmfm.github.io/2016/06/04/doukaku-e04.html
- Ruby のコードはこちら: http://qiita.com/emattsan/items/cb65001e2b4b76faf6cd
- 各人の実装へのリンク集はこちら: http://qiita.com/mtsmfm/items/6d9112fcc568908caaba

## C++

```cpp:orde04.cpp
#include <iostream>
#include <string>
#include <numeric>

struct Roll
{
    unsigned int rock;

    Roll(unsigned int rock) : rock(rock) {}

    unsigned int operator () (unsigned int death_route, char b)
    {
        const unsigned int branch      = (0x181u >> (8 - (b - '0'))) & 0xff;

        if(rock & branch)
        {
            rock ^= branch;
            return death_route | branch;
        }

        if(((death_route ^ branch) & branch) * (death_route & branch))
        {
            return death_route ^ branch;
        }

        return death_route;
    }
};

std::string solve(const std::string& input)
{
    auto i = std::find(input.begin(), input.end(), ':');
    std::string branches(input.begin(), i);
    unsigned int rock = 1u << (*++i - 'A');

    unsigned int death_route = std::accumulate(branches.begin(), branches.end(), rock, Roll(rock));

    std::string actual;

    for(int i = 0; i < 8; ++i)
    {
        if(((death_route >> i) & 1) == 0)
        {
            actual += ('A' + i);
        }
    }

    return actual;
}

void test(const std::string& input, const std::string& expected)
{
    std::string actual = solve(input);
    if(actual == expected)
    {
        std::cout << "\x1b[32m.\x1b[0m" << std::flush;
    }
    else
    {
        std::cout
          << "\x1b[31m\n"
          << "input:    " << input << "\n"
          << "expected: " << expected << "\n"
          << "actual:   " << actual << "\x1b[0m\n"
          << std::flush;
    }
}

int main(int, char* argv[])
{
    test("2512:C", "DEFGH");
    test("1:A", "CDEFGH");
    test(":C", "ABDEFGH");
    test("2345:B", "AGH");
    test("1256:E", "ABCDH");
    test("1228:A", "ADEFG");
    test("5623:B", "AEFGH");
    test("8157:C", "ABDEFGH");
    test("74767:E", "ABCFGH");
    test("88717:D", "ABCEFGH");
    test("148647:A", "ACDEFH");
    test("374258:H", "BCDEFH");
    test("6647768:F", "ABCDEH");
    test("4786317:E", "ABFGH");
    test("3456781:C", "");
    test("225721686547123:C", "CEF");
    test("2765356148824666:F", "ABCDEH");
    test("42318287535641783:F", "BDE");
    test("584423584751745261:D", "FGH");
    test("8811873415472513884:D", "CFG");
    test("74817442725737422451:H", "BCDEF");
    test("223188865746766511566:C", "ABGH");
    test("2763666483242552567747:F", "ABCG");
    test("76724442325377753577138:E", "EG");
    test("327328486656448784712618:B", "");
    test("4884637666662548114774288:D", "DGH");
    test("84226765313786654637511248:H", "DEF");
    test("486142154163288126476238756:A", "CDF");
    test("1836275732415226326155464567:F", "BCD");
    test("62544434452376661746517374245:G", "G");
    test("381352782758218463842725673473:B", "A");

    std::cout << std::endl;

    return 0;
}
```

## Haskell

```haskell:orde04.hs
import Data.Bits
import Data.Char
import Data.List
import Data.Word

roll :: (Word, Word) -> Word -> (Word, Word)
roll (rock, death_route) branch
  | rock .&. branch /= 0 = (rock `xor` branch, death_route .|. branch)
  | ((death_route `xor` branch) .&. branch) * (death_route .&. branch) /= 0 = (rock, death_route `xor` branch)
  | otherwise = (rock, death_route)

runOver = map fst.filter (\(c, b) -> b == 0).zip ['A'..'H'].unfoldr (\n -> Just (n .&. 1, shiftR n 1))

solve input =
  runOver $ snd $ foldl' roll (rock, rock) branches
  where
    (branches, rock) = (\(bs, [':', r]) -> (map (\b -> (shiftR 0x181 (8 - (ord b - ord '0'))) .&. 0xff::Word) bs, shiftL (1::Word) (ord r - ord 'A'))) $ break (== ':') input

test input expected =
  if actual == expected
  then
    putStr "\x1b[32m.\x1b[0m"
  else do
    putStrLn "\x1b[31m"
    putStr "input:    "
    putStrLn $ input
    putStr "expected: "
    putStrLn $ expected
    putStr "actual:   "
    putStrLn $ actual
    putStr "\x1b[0m"
  where
    actual = solve input

main = do
  test "2512:C" "DEFGH"
  test "1:A" "CDEFGH"
  test ":C" "ABDEFGH"
  test "2345:B" "AGH"
  test "1256:E" "ABCDH"
  test "1228:A" "ADEFG"
  test "5623:B" "AEFGH"
  test "8157:C" "ABDEFGH"
  test "74767:E" "ABCFGH"
  test "88717:D" "ABCEFGH"
  test "148647:A" "ACDEFH"
  test "374258:H" "BCDEFH"
  test "6647768:F" "ABCDEH"
  test "4786317:E" "ABFGH"
  test "3456781:C" ""
  test "225721686547123:C" "CEF"
  test "2765356148824666:F" "ABCDEH"
  test "42318287535641783:F" "BDE"
  test "584423584751745261:D" "FGH"
  test "8811873415472513884:D" "CFG"
  test "74817442725737422451:H" "BCDEF"
  test "223188865746766511566:C" "ABGH"
  test "2763666483242552567747:F" "ABCG"
  test "76724442325377753577138:E" "EG"
  test "327328486656448784712618:B" ""
  test "4884637666662548114774288:D" "DGH"
  test "84226765313786654637511248:H" "DEF"
  test "486142154163288126476238756:A" "CDF"
  test "1836275732415226326155464567:F" "BCD"
  test "62544434452376661746517374245:G" "G"
  test "381352782758218463842725673473:B" "A"
  putStrLn ""
```