Skip to content

Commit

Permalink
rename operations - add graph
Browse files Browse the repository at this point in the history
  • Loading branch information
e-silvestri committed Jan 3, 2022
1 parent fe656b7 commit a37c966
Show file tree
Hide file tree
Showing 17 changed files with 850 additions and 87 deletions.
39 changes: 39 additions & 0 deletions PtVzzlexMasCake.Tests/DijkstraSolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,44 @@ internal static IEnumerable<Node> SolveFull(int baseTwoExponent)
}
return extracted;
}
internal static IDictionary<BigInteger, ICollection<ICollection<Operation>>> FindAllSolutions(int baseTwoExponent)
{
BigInteger maxValue = new BigInteger(1 << baseTwoExponent);
var extracted = new Dictionary<BigInteger, ICollection<ICollection<Operation>>>();
var costs = new Dictionary<BigInteger, int>();
var queue = new PriorityQueue<Node, int>();
var root = new Node(0, 1, new List<Operation>());
queue.Enqueue(root, root.Cost);
costs[root.Value] = 0;
while (queue.TryDequeue(out var current, out _))
{
ICollection<ICollection<Operation>> solutions;
if (!extracted.TryGetValue(current.Value, out solutions))
{
solutions = new List<ICollection<Operation>>();
solutions.Add(current.Operations);
extracted.Add(current.Value, solutions);
}
else
{
if (solutions.First().Count == current.Operations.Count)
{
solutions.Add(current.Operations);
}
}
foreach (Node node in current.Star())
{
if ((!costs.TryGetValue(node.Value, out var prevCost) ||
node.Cost <= prevCost) && node.Value <= maxValue)
{
costs[node.Value] = node.Cost;
queue.Enqueue(node, node.Cost);
}
}

}
return extracted;
}
}
}

12 changes: 6 additions & 6 deletions PtVzzlexMasCake.Tests/Node.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ public Node(int cost, BigInteger value, List<Operation> operations)
internal IEnumerable<Node> Star()
{
var divideByTwo = new List<Operation>(Operations);
divideByTwo.Add(Operation.Halve);
divideByTwo.Add(Operation.Div);
yield return new Node(Cost + 1, Value * 2, divideByTwo);

if (Value > 1)
{
var addOne = new List<Operation>(Operations);
addOne.Add(Operation.AddOne);
addOne.Add(Operation.Add);
yield return new Node(Cost + 1, Value - 1, addOne);
}

var subtractOne = new List<Operation>(Operations);
subtractOne.Add(Operation.SubtractOne);
yield return new Node(Cost + 1, Value + 1, subtractOne);
var subtractOne = new List<Operation>(Operations);
subtractOne.Add(Operation.Sub);
yield return new Node(Cost + 1, Value + 1, subtractOne);
}
}

public override bool Equals(object? obj)
Expand Down
6 changes: 3 additions & 3 deletions PtVzzlexMasCake.Tests/Operator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ public static BigInteger Execute(Operation operation, BigInteger value)
{
switch (operation)
{
case Operation.Halve:
case Operation.Div:
return value / 2;
case Operation.AddOne:
case Operation.Add:
return value +1;
case Operation.SubtractOne:
case Operation.Sub:
return value -1;
default:
return value;
Expand Down
1 change: 1 addition & 0 deletions PtVzzlexMasCake.Tests/PtVzzlexMasCake.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutomaticGraphLayout.Drawing" Version="1.1.12" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.8" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
Expand Down
94 changes: 92 additions & 2 deletions PtVzzlexMasCake.Tests/PuzzleSolverTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Msagl.Core.Geometry;
using Microsoft.Msagl.Core.Geometry.Curves;
using Microsoft.Msagl.Drawing;
using Microsoft.Msagl.Layout.Layered;
using Microsoft.Msagl.Miscellaneous;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Numerics;

namespace PtVzzlexMasCake.Tests
Expand All @@ -24,7 +29,7 @@ public void PuzzleSolverTest()
var initialValue = item.Value;
foreach (var operation in solution)
{
initialValue = Operator.Execute(operation,initialValue);
initialValue = Operator.Execute(operation, initialValue);
}
Assert.AreEqual(1, initialValue);

Expand Down Expand Up @@ -55,5 +60,90 @@ public void PuzzleSolverTest()
}
}
}

[TestMethod]
public void FindAllSolutions()
{
var result = DijkstraSolver.FindAllSolutions(baseTwoExponent);
var maxSolutions = result.Values.Max(x => x.Count);
var numberWithMaxSolutions = result.Where(x => x.Value.Count == maxSolutions).ToList();
using var sw = new StreamWriter("../../../multipleSolutions.txt");
foreach (var item in numberWithMaxSolutions)
{
sw.WriteLine(item.Key);
foreach (var item2 in item.Value)
{
sw.WriteLine(string.Join(" ", item2.Reverse()));
}
sw.WriteLine();
}
var drawingGraph = new Graph();
var interestingNodes = result; // result.Where(x => x.Value.Count == 1);
foreach (var item in interestingNodes)
{
drawingGraph.AddNode(item.Key.ToString()).LabelText = item.Key.ToString();
}
foreach (var item in interestingNodes)
{
if (item.Value.Any(x => x.Count > 0))
{
foreach (var item1 in item.Value.Select(x => x.Last()).Distinct())
{
drawingGraph.AddEdge(
item.Key.ToString(),
Operator.Execute(item1, item.Key).ToString()).
LabelText = item1.ToString();
}
}
}
drawingGraph.CreateGeometryGraph();


// Now the drawing graph elements point to the corresponding geometry elements,
// however the node boundary curves are not set.
// Setting the node boundaries
foreach (var n in drawingGraph.Nodes)
{
// Ideally we should look at the drawing node attributes, and figure out, the required node size
// I am not sure how to find out the size of a string rendered in SVG. Here, we just blindly assign to each node a rectangle with width 60 and height 40, and round its corners.
n.GeometryNode.BoundaryCurve = CurveFactory.CreateRectangleWithRoundedCorners(60, 40, 3, 2, new Point(0, 0));
}

AssignLabelsDimensions(drawingGraph);

LayoutHelpers.CalculateLayout(drawingGraph.GeometryGraph, new SugiyamaLayoutSettings(), null);
PrintSvgAsString(drawingGraph);
}
static void AssignLabelsDimensions(Graph drawingGraph)
{
// In general, the label dimensions should depend on the viewer
foreach (var na in drawingGraph.Nodes)
{
na.Label.Width = na.Width * 0.6;
na.Label.Height = 40;
}

// init geometry labels as well
foreach (var de in drawingGraph.Edges)
{
// again setting the dimensions, that should depend on Drawing.Label and the viewer, blindly
de.Label.GeometryLabel.Width = 140;
de.Label.GeometryLabel.Height = 60;
}
}

static void PrintSvgAsString(Graph drawingGraph)
{
var ms = new MemoryStream();
var writer = new StreamWriter(ms);
var svgWriter = new SvgGraphWriter(writer.BaseStream, drawingGraph);
svgWriter.Write();
// get the string from MemoryStream
ms.Position = 0;
var sr = new StreamReader(ms);
var myStr = sr.ReadToEnd();
using var sw = new StreamWriter("../../../../graph.svg");
sw.Write(myStr);
}
}
}
10 changes: 5 additions & 5 deletions PtVzzlexMasCake.Tests/Resources/11.expected.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
11
AddOne
Halve
Halve
SubtractOne
Halve
Add
Div
Div
Sub
Div
10 changes: 5 additions & 5 deletions PtVzzlexMasCake.Tests/Resources/13.expected.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
13
SubtractOne
Halve
Halve
SubtractOne
Halve
Sub
Div
Div
Sub
Div
10 changes: 5 additions & 5 deletions PtVzzlexMasCake.Tests/Resources/15.expected.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
15
AddOne
Halve
Halve
Halve
Halve
Add
Div
Div
Div
Div
4 changes: 2 additions & 2 deletions PtVzzlexMasCake.Tests/Resources/3.expected.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
3
SubtractOne
Halve
Sub
Div
6 changes: 3 additions & 3 deletions PtVzzlexMasCake.Tests/Resources/5.expected.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
5
SubtractOne
Halve
Halve
Sub
Div
Div
8 changes: 4 additions & 4 deletions PtVzzlexMasCake.Tests/Resources/7.expected.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
7
AddOne
Halve
Halve
Halve
Add
Div
Div
Div
8 changes: 4 additions & 4 deletions PtVzzlexMasCake.Tests/Resources/9.expected.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
9
SubtractOne
Halve
Halve
Halve
Sub
Div
Div
Div
3 changes: 2 additions & 1 deletion PtVzzlexMasCake.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PtVzzlexMasCake", "PtVzzlexMasCake\PtVzzlexMasCake.csproj", "{3781B5B1-981A-4A30-B2CF-4FAA995CBCC0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PtVzzlexMasCake.Tests", "PtVzzlexMasCake.Tests\PtVzzlexMasCake.Tests.csproj", "{5FE2CB57-39DE-4584-B033-10D2ECCE243A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PtVzzlexMasCake.Tests", "PtVzzlexMasCake.Tests\PtVzzlexMasCake.Tests.csproj", "{5FE2CB57-39DE-4584-B033-10D2ECCE243A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6E2BA7B5-4B99-466E-983C-CE6EADEA56EB}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
costs.png = costs.png
dotnet-install.ps1 = dotnet-install.ps1
dotnet-install.sh = dotnet-install.sh
graph.svg = graph.svg
README.md = README.md
EndProjectSection
EndProject
Expand Down
18 changes: 9 additions & 9 deletions PtVzzlexMasCake/Operation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
{
internal enum Operation
{
Halve,
AddOne,
SubtractOne
Div,
Add,
Sub
}

internal static class OperationExtensions
Expand All @@ -13,12 +13,12 @@ public static string OperationToString(this Operation operation)
{
switch (operation)
{
case Operation.AddOne:
return nameof(Operation.AddOne);
case Operation.SubtractOne:
return nameof(Operation.SubtractOne);
case Operation.Halve:
return nameof(Operation.Halve);
case Operation.Add:
return nameof(Operation.Add);
case Operation.Sub:
return nameof(Operation.Sub);
case Operation.Div:
return nameof(Operation.Div);
default:
return "";
}
Expand Down
8 changes: 4 additions & 4 deletions PtVzzlexMasCake/PuzzleSolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,24 @@ public static List<Operation> Solve(BigInteger value)
{
if (value.IsEven)
{
solution.Add(Operation.Halve);
solution.Add(Operation.Div);
value = value / 2;
}
else
{
if (value == 3)
{
solution.Add(Operation.SubtractOne);
solution.Add(Operation.Sub);
value = value - 1;
}
else if (((value + 1) / 2).IsEven)
{
solution.Add(Operation.AddOne);
solution.Add(Operation.Add);
value = value + 1;
}
else
{
solution.Add(Operation.SubtractOne);
solution.Add(Operation.Sub);
value = value - 1;
}
}
Expand Down
Loading

0 comments on commit a37c966

Please sign in to comment.