From 4ee6e23917389bf7dbe89b2b5bda588e21a615bf Mon Sep 17 00:00:00 2001
From: Xevion
Date: Sun, 18 Dec 2022 01:54:22 -0600
Subject: [PATCH] Further explanation, add BoxLoop graphic, move getColors into
helpers.ts
---
src/components/BoxLoop.tsx | 74 ++++++++++++++++++++++++++++++++++++++
src/pages/index.tsx | 36 ++++++++++++++++++-
src/utils/helpers.ts | 27 ++++++++++++++
3 files changed, 136 insertions(+), 1 deletion(-)
create mode 100644 src/components/BoxLoop.tsx
diff --git a/src/components/BoxLoop.tsx b/src/components/BoxLoop.tsx
new file mode 100644
index 0000000..54ebe83
--- /dev/null
+++ b/src/components/BoxLoop.tsx
@@ -0,0 +1,74 @@
+import React, {FunctionComponent, useState} from "react";
+import Chance from "chance";
+import {classNames, getColor, range} from "@/utils/helpers";
+import {create} from "domain";
+import BoxGraphic from "@/components/BoxGraphic";
+import Xarrow from "react-xarrows";
+
+interface BoxLoopProps {
+
+}
+
+/**
+ * Creates a loop of numbers in the given range & length.
+ * @param loopRange An array describing the range of numbers to pick from.
+ * @param count The number of items in the loop.
+ */
+function createLoop(loopRange: [number, number], count: number): { start: number, loop: Record, list: number[] } | undefined {
+ if (loopRange[0] >= loopRange[1]) return undefined;
+ const chance = new Chance();
+ const available = chance.pickset(range(loopRange[0], loopRange[1]), Math.min(count, loopRange[1] - loopRange[0]));
+ const loop: Record = {};
+
+ const list: number[] = [];
+ const start = available.pop() as number;
+ let current = start;
+ list.push(start);
+ while (available.length > 0) {
+ const next = available.pop() as number;
+ loop[current] = next;
+ list.push(next);
+ current = next;
+ }
+ loop[current] = start; // Finish the loop
+
+ return {start, loop, list};
+}
+
+const BoxLoop: FunctionComponent = ({}: BoxLoopProps) => {
+ const count = 5;
+ const [{loop, start, list}] = useState(createLoop([1, 100], count)!);
+
+ return
+ {list.map((i, index) => {
+ const [sourceKey, destinationKey] = [`x-${i}`, `x-${loop[i]}`];
+ let anchor = ["top", "bottom"];
+ if (index % 2 == 0) anchor.reverse()
+ const isLast = index == count - 1;
+
+ return (
+
+
+
{loop[i]}
+
+ {i}
+
+ {loop[i] ?
+
: null}
+
+
+ );
+ })}
+
+}
+
+export default BoxLoop;
\ No newline at end of file
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index bfaba67..ce7fbcf 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -3,6 +3,7 @@ import Head from "next/head";
import BoxTable from "@/components/BoxTable";
import NoSSR from "react-no-ssr";
import Page from "@/components/Page";
+import BoxLoop from "@/components/BoxLoop";
const Home: NextPage = () => {
return (
@@ -45,7 +46,7 @@ const Home: NextPage = () => {
All prisoners must be successful - if even one fails, they all lose.
- Prisoners cannot mark, relay or in any way communicate with each other.
+ Prisoners cannot mark boxes, relay information or in any way communicate with each other.
@@ -53,6 +54,39 @@ const Home: NextPage = () => {
this challenge to be impossible - but it turns out there is a strategy that guarantees a
31% chance of success!
+
+ Here's how it works:
+
+ -
+ Go to the box with your number labeled on top of it. Open it.
+
+ -
+ If the number inside is not your slip, then go to the box with the number you just
+ found.
+
+ -
+ Repeat until you find your number.
+
+
+ Due to an interesting mathematical quirk of some (assumed) properties of the game,
+ the boxes have an interesting structure to their existence.
+
+
+
+
+
+ No matter what number of configuration of boxes is given, a loop, a sequence of numbers that
+ will
+ return to the first one you picked, will exist.
+
+ Given that there are only 100 boxes, you won't find a loop that goes on forever,
+ and you won't find a box without a number under it (one that goes nowhere).
+
+
+
+ Essentially, by following the boxes, it is certain that you will find your slip.
+
+
diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts
index 9a64e46..2dd0e9a 100644
--- a/src/utils/helpers.ts
+++ b/src/utils/helpers.ts
@@ -1,3 +1,25 @@
+import Chance from "chance";
+
+const colors = [
+ "#EF4444",
+ "#F97316",
+ "#F59E0B",
+ "#EAB308",
+ "#84CC16",
+ "#22C55E",
+ "#10B981",
+ "#14B8A6",
+ "#06B6D4",
+ "#0EA5E9",
+ "#3B82F6",
+ "#6366F1",
+ "#8B5CF6",
+ "#A855F7",
+ "#D946EF",
+ "#EC4899",
+ "#F43F5E",
+]
+
export const range = (start: number, stop: number, step = 1) =>
Array.from({length: (stop - start) / step + 1}, (_, i) => start + i * step);
@@ -7,4 +29,9 @@ export function classNames(...classes: (string | null | undefined)[]) {
export function sum(a: number, b: number): number {
return a + b;
+}
+
+export function getColor(seed: number) {
+ const chance = Chance(seed);
+ return chance.pickone(colors);
}
\ No newline at end of file