Wireworld/C sharp
<lang c sharp>using System; using System.Collections.Generic; using System.Diagnostics; using System.Text;
namespace Wireworld {
internal static class Program { private static void Main() { const string sample = // Two clock generators sending electrons into an XOR gate. @" tH......
. ......
...Ht... . .... . ..... .... ......tH .
. ......
...Ht...";
var state = new Wireworld(sample);
for (uint i = 0; i <= 12; i++) { state.Step((i == 0 ? i : 1)); state.Print(); } }
private static void Print(this Wireworld state) { Console.WriteLine("Generation {0}", state.Generation); Console.WriteLine(state.StateString); Console.WriteLine("Generated in {0} ms.", state.MillisecondsToGenerate); }
private class Wireworld { private enum Cell : byte { Empty, Conductor, ElectronHead, ElectronTail }
public Wireworld(string state, char conductor = '.', char head = 'H', char tail = 't', char empty = ' ') { _empty = empty; _conductor = conductor; _head = head; _tail = tail;
_stateCells = GetCellsFromString(state); StateString = GetStringFromCells(_stateCells);
_stopwatch = new Stopwatch(); }
public void Step(uint steps = 1) { _stopwatch.Restart();
for (int step = 0; step < steps; step++) { /* * Copies the current state of the cells to a new variable so we * can read from this variable and write to the current cells. */ var oldState = new Cell[_stateCells.Length][]; for (int row = 0; row < _stateCells.Length; row++) oldState[row] = (Cell[]) _stateCells[row].Clone();
for (int i = 0; i < _stateCells.Length; i++) { for (int o = 0; o < _stateCells[i].Length; o++) { /* * Check the value of the current cell (i, o). * * If it's a conductor, if 1 or 2 neighbors are electron heads, * we will change this cell to an electron head. * * If it's an electron head, we will turn this cell into an * electron tail. * * If it's an electron tail, we will turn this cell into a * conductor. */ switch (oldState[i][o]) { case Cell.Conductor: var neighbors = GetNeighborCount(oldState, i, o, Cell.ElectronHead); if (neighbors == 1 || neighbors == 2) _stateCells[i][o] = Cell.ElectronHead; break; case Cell.ElectronHead: _stateCells[i][o] = Cell.ElectronTail; break; case Cell.ElectronTail: _stateCells[i][o] = Cell.Conductor; break; } } } }
_stopwatch.Stop();
Generation += steps;
// Set the current state string to the current state, for printing. StateString = GetStringFromCells(_stateCells); }
private byte GetNeighborCount(Cell[][] cells, int row, int column, Cell value) { byte neighbors = 0;
// If the row of the cell is 0, we will start checking from 0 cells above. int rowStart = row == 0 ? 0 : -1;
// If the row of the cell is that last row, we will end check 0 cells below. int rowEnd = row == cells.Length - 1 ? 0 : 1;
// If the column of the cell is 0, we will start checking from 0 cells to the left. int columnStart = column == 0 ? 0 : -1;
for (int i = rowStart; i <= rowEnd; i++) { /* If the column of the cell is at or after the last column in this row, then we will * stop checking at the last column. */ int columnEnd = column >= cells[row + i].Length - 1 ? (cells[row + i].Length - 1) - column : 1;
for (int o = columnStart; o <= columnEnd; o++) { /* * If the current cell is the same as the specified cell, then we will continue * checking on the next cell. Otherwise, if the current cell is of the specified * value, we will add to our neighbor count. */
if (i == 0 && o == 0) continue; if (cells[row + i][column + o] == value) neighbors++; } }
return neighbors; }
private Cell[][] GetCellsFromString(string state) { var lines = state.Replace("\r", "").Split('\n'); var cells = new Cell[lines.Length][];
for (int i = 0; i < lines.Length; i++) { string line = lines[i]; cells[i] = new Cell[line.Length];
for (int o = 0; o < line.Length; o++) { char c = line[o]; Cell thisState;
if (c == _empty) thisState = Cell.Empty; else if (c == _conductor) thisState = Cell.Conductor; else if (c == _head) thisState = Cell.ElectronHead; else if (c == _tail) thisState = Cell.ElectronTail; else throw new ArgumentException("State string contains invalid characters.", "state");
cells[i][o] = thisState; } }
return cells; }
private string GetStringFromCells(IEnumerable<Cell[]> cells) { var outputString = new StringBuilder();
foreach (var row in cells) { foreach (var cell in row) { switch (cell) { case Cell.Empty: outputString.Append(_empty); break; case Cell.Conductor: outputString.Append(_conductor); break; case Cell.ElectronHead: outputString.Append(_head); break; case Cell.ElectronTail: outputString.Append(_tail); break; } } outputString.AppendLine(); }
return outputString.ToString(); }
public uint Generation { get; private set; }
public long MillisecondsToGenerate { get { return _stopwatch.ElapsedMilliseconds; } }
public string StateString { get; private set; }
private readonly Cell[][] _stateCells; private readonly Stopwatch _stopwatch;
private readonly char _empty; private readonly char _conductor; private readonly char _head; private readonly char _tail; } }
}</lang>
Sample Output
Generation 0 tH...... . ...... ...Ht... . .... . ..... .... ......tH . . ...... ...Ht... Generated in 0 ms. Generation 1 .tH..... . ...... ..Ht.... . .... . ..... .... .......t . . H..... ..Ht.... Generated in 0 ms. Generation 2 ..tH.... . ...... .Ht..... . .... . ..... .... ........ . . tH.... .Ht....H Generated in 0 ms. Generation 3 ...tH... . ...... Ht...... . .... . ..... .... ........ . . .tH... Ht....Ht Generated in 0 ms. Generation 4 ....tH.. H ...... t....... . .... . ..... .... ........ . H ..tH.. t....Ht. Generated in 0 ms. Generation 5 H....tH. t ...... ........ . .... . ..... .... H....... . t ...tH. ....Ht.. Generated in 0 ms. Generation 6 tH....tH . ...... ........ . .... . ..... .... tH...... . . ....tH ...Ht... Generated in 0 ms. Generation 7 .tH....t . H..... ........ . .... . ..... .... .tH..... H . .....t ..Ht.... Generated in 0 ms. Generation 8 ..tH.... . tH.... .......H . .... . ..... HHH. ..tH.... t . ...... .Ht..... Generated in 0 ms. Generation 9 ...tH... . .tH... ......Ht . .... H H.... tttH ...tH... . . ...... Ht...... Generated in 0 ms. Generation 10 ....tH.. . ..tH.. .....Ht. . HHHH t tH... ...t ....tH.. . H ...... t....... Generated in 0 ms. Generation 11 .....tH. . ...tH. ....Ht.. . tttt . .tH.. .... H....tH. . t ...... ........ Generated in 0 ms. Generation 12 ......tH . ....tH ...Ht... . .... . ..tH. .... tH....tH . . ...... ........ Generated in 0 ms.