Skip to content

Instantly share code, notes, and snippets.

@cawhitworth
Last active May 30, 2018 01:38
Show Gist options
  • Save cawhitworth/8c7ac7d309750a7dde73 to your computer and use it in GitHub Desktop.
Save cawhitworth/8c7ac7d309750a7dde73 to your computer and use it in GitHub Desktop.
Countdown solver in C#
using System;
using System.Collections.Generic;
using System.Linq;
namespace Countdown
{
internal interface IExpression { };
class Op : IExpression
{
public Func<int, int, int> Func { get; private set; }
public string Name { get; private set; }
public Op(string name, Func<int, int, int> op)
{
Func = op;
Name = name;
}
public override string ToString()
{
return Name;
}
}
class Num : IExpression
{
public int Val { get; set; }
public Num(int val) { Val = val; }
public override string ToString()
{
return Val.ToString();
}
}
class Program
{
static readonly Random r = new Random();
private static readonly Op[] Ops =
{
new Op("+", (a, b) => a + b),
new Op("-", (a, b) => a - b),
new Op("*", (a, b) => a * b),
new Op("/", (a, b) =>
{
if (a%b != 0)
{
throw new ArgumentException();
}
return a/b;
})
};
static void Main(string[] args)
{
var target = r.Next(1000);
var stack = new Stack<IExpression>();
var numbers = new List<int>
{
OneFromTheTop(),
AnyOther(),
AnyOther(),
AnyOther(),
AnyOther(),
AnyOther(),
};
Console.WriteLine("Target {0}", target);
Console.Write("Using {0}", string.Join(", ", numbers));
Console.WriteLine();
NextGen(numbers, stack, target);
}
private static void NextGen(List<int> numbers, Stack<IExpression> stack, int target)
{
for (int i = 0; i < numbers.Count; i++)
{
var n = numbers[i];
var nextList = new List<int>(numbers);
nextList.RemoveAt(i);
stack.Push(new Num(n));
try
{
var val = Evaluate(stack);
if (val == target)
{
Print(stack);
}
if (val < 0) throw new Exception();
foreach (var op in Ops)
{
stack.Push(op);
NextGen(nextList, stack, target);
stack.Pop();
}
}
catch
{ }
stack.Pop();
}
}
private static void Print(IEnumerable<IExpression> stack)
{
foreach (var expression in stack.Reverse())
{
Console.Write(expression);
}
Console.WriteLine();
}
private static int Evaluate(IEnumerable<IExpression> stack)
{
int acc = 0;
Op currentOp = null;
foreach (var expression in stack.Reverse())
{
if (expression is Num)
{
int val = (expression as Num).Val;
acc = currentOp != null ? currentOp.Func(acc, val) : val;
}
else
{
currentOp = expression as Op;
}
}
return acc;
}
private static int OneFromTheTop()
{
return PickFrom(25, 50, 75, 100);
}
private static int AnyOther()
{
return PickFrom(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}
private static int PickFrom(params int[] numbers)
{
return numbers[r.Next(numbers.Length)];
}
}
}
@cawhitworth
Copy link
Author

The output isn't mathematically correct - it should be read strictly left-to-right, there's no operator precedence. It also doesn't attempt to eliminate equivalent solutions. Both of these problems might be interesting extensions for a kata :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment