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:
    +

      +
    1. + Go to the box with your number labeled on top of it. Open it. +
    2. +
    3. + If the number inside is not your slip, then go to the box with the number you just + found. +
    4. +
    5. + Repeat until you find your number. +
    6. +
    + 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