Created
December 26, 2019 13:04
-
-
Save nesteruk/71406d6bf6065e2202fc630bc96c837a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.ComponentModel; | |
using System.Linq; | |
using System.Reflection; | |
using System.Text; | |
namespace PatternDemoCore | |
{ | |
public enum Op : byte | |
{ | |
[Description("*")] | |
Mul = 0, | |
[Description("/")] | |
Div = 1, | |
[Description("+")] | |
Add = 2, | |
[Description("—")] | |
Sub = 3 | |
} | |
public static class OpExtensions | |
{ | |
static OpExtensions() | |
{ | |
var type = typeof(Op); | |
foreach (Op op in Enum.GetValues(type)) | |
{ | |
MemberInfo[] memInfo = type.GetMember(op.ToString()); | |
if (memInfo.Length > 0) | |
{ | |
var attrs = memInfo[0].GetCustomAttributes( | |
typeof(DescriptionAttribute), false); | |
if (attrs.Length > 0) | |
{ | |
opNames[op] = ((DescriptionAttribute) attrs[0]).Description[0]; | |
} | |
} | |
} | |
} | |
private static readonly Dictionary<Op, char> opNames | |
= new Dictionary<Op, char>(); | |
public static char Name(this Op op) | |
{ | |
return opNames[op]; | |
} | |
private static readonly Dictionary<Op, Func<int, int, int>> | |
opImpl = new Dictionary<Op, Func<int, int, int>> | |
{ | |
[Op.Mul] = ((x,y) => x*y), | |
[Op.Div] = ((x,y) => x/y), | |
[Op.Add] = ((x,y) => x+y), | |
[Op.Sub] = ((x,y) => x-y), | |
}; | |
public static int Call(this Op op, int x, int y) | |
{ | |
return opImpl[op](x, y); | |
} | |
} | |
public class Problem | |
{ | |
private readonly List<int> numbers; | |
private readonly List<Op> ops; | |
public Problem( | |
IEnumerable<int> numbers, | |
IEnumerable<Op> ops) | |
{ | |
this.numbers = new List<int>(numbers); | |
this.ops = new List<Op>(ops); | |
} | |
public int Eval() | |
{ | |
var opGroups = new[] | |
{ | |
new[] {Op.Mul, Op.Div}, | |
new[] {Op.Add, Op.Sub} | |
}; | |
startAgain: | |
foreach (var group in opGroups) | |
{ | |
for (var idx = 0; idx < ops.Count; ++idx) | |
{ | |
var op = ops[idx]; | |
if (group.Contains(op)) | |
{ | |
numbers[idx] = op.Call(numbers[idx], numbers[idx + 1]); | |
numbers.RemoveAt(idx+1); | |
ops.RemoveAt(idx); | |
if (numbers.Count == 1) return numbers[0]; | |
goto startAgain; | |
} | |
} | |
} | |
return numbers[0]; | |
} | |
public override string ToString() | |
{ | |
var sb = new StringBuilder(); | |
int i = 0; | |
for (; i < ops.Count; ++i) | |
{ | |
sb.Append(numbers[i]); | |
sb.Append(ops[i].Name()); | |
} | |
sb.Append(numbers[i]); | |
return sb.ToString(); | |
} | |
} | |
public class TwoBitSet | |
{ | |
private readonly ulong data; | |
// 64 bit --> 32 values | |
public TwoBitSet(ulong data) | |
{ | |
this.data = data; | |
} | |
public static implicit operator TwoBitSet(ulong value) | |
{ | |
return new TwoBitSet(value); | |
} | |
public byte this[int index] | |
{ | |
get | |
{ | |
var shift = index << 1; | |
ulong mask = (0b11U << shift); | |
return (byte) ((data & mask) >> shift); | |
} | |
} | |
} | |
public class Demo | |
{ | |
public static void Main(string[] args) | |
{ | |
// 2 2 2 2 | |
// ↑ ↑ ↑ | |
var numbers = new[] {2, 2, 2, 2, 2}; | |
int numberOfOps = numbers.Length - 1; | |
for (int result = 0; result <= 10; ++result) | |
{ | |
for (ulong key = 0UL; key < (1UL << 2 * numberOfOps); ++key) | |
{ | |
var tbs = new TwoBitSet(key); | |
var ops = Enumerable.Range(0, numberOfOps) | |
.Select(i => tbs[i]).Cast<Op>().ToArray(); | |
var problem = new Problem(numbers, ops); | |
var s = problem.ToString(); | |
if (problem.Eval() == result) | |
{ | |
Console.WriteLine($"{s} = {result}"); | |
break; | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment