예제 #1
0
파일: Program.cs 프로젝트: rstarkov/i4c
        private static void SaveComprCounters(Compressor compr, string destDir)
        {
            TextTable table = new TextTable {
                DefaultAlignment = HorizontalTextAlignment.Right, ColumnSpacing = 3, MaxWidth = int.MaxValue
            };

            compr.ComputeCounterTotals();

            int rownum      = 0;
            int indent_prev = 0;

            foreach (var key in compr.Counters.Keys.Order())
            {
                int indent = 4 * key.ToCharArray().Count(c => c == '|');
                if (indent < indent_prev)
                {
                    rownum++;
                }
                indent_prev = indent;
                table.SetCell(0, rownum, new string(' ', indent) + key.Split('|').Last(), alignment: HorizontalTextAlignment.Left);
                table.SetCell(1, rownum, Math.Round(compr.Counters[key], 3).ToString("#,0"));
                rownum++;
            }

            File.WriteAllText(Path.Combine(destDir, "counters.txt"), table.ToString());
        }
예제 #2
0
        public static void Test()
        {
            var ruleCombinationHistogram  = new Dictionary <string, int>();
            var numCorrectCardsHistorgram = new Dictionary <int, Dictionary <string, int> >();
            var numWrongCardsHistorgram   = new Dictionary <int, Dictionary <string, int> >();

            const int numIter  = 2000;
            var       rnd      = new Random();
            var       numRules = 0;

            for (int iter = 0; iter < numIter; iter++)
            {
                var rules = getRules(Edgework.Generate(5, 10, false, rnd));
                numRules = rules.Length;
                var puzzle = generatePuzzle(rules, rnd);

                var rulesIndexesStr = puzzle.ActiveRuleIndexes.Order().Select(r => r + 1).JoinString(",");
                ruleCombinationHistogram.IncSafe(rulesIndexesStr);
                numCorrectCardsHistorgram.IncSafe(puzzle.CorrectCards.Length, rulesIndexesStr);
                numWrongCardsHistorgram.IncSafe(puzzle.WrongCards.Length, rulesIndexesStr);
            }

            foreach (var kvp in ruleCombinationHistogram.OrderBy(k => k.Key))
            {
                Console.WriteLine($"{kvp.Key} = {kvp.Value * 100.0 / numIter:0.0}%");
            }
            Console.WriteLine($"Factor: {ruleCombinationHistogram.Max(k => k.Value) / (double) ruleCombinationHistogram.Min(k => k.Value):0.0}");
            Console.WriteLine();
            for (int i = 0; i < numRules; i++)
            {
                Console.WriteLine($"Rule #{i + 1} = {ruleCombinationHistogram.Where(p => p.Key.Contains((i + 1).ToString())).Sum(p => p.Value) * 100.0 / numIter:0.0}%");
            }
            Console.WriteLine();
            ConsoleUtil.WriteLine("Distribution of number of correct cards:".Color(ConsoleColor.White));
            var tt = new TextTable {
                ColumnSpacing = 2
            };
            var rulesIndexesStrs = ruleCombinationHistogram.Keys.Order().ToArray();

            for (int col = 0; col < rulesIndexesStrs.Length; col++)
            {
                tt.SetCell(col + 1, 0, rulesIndexesStrs[col].Color(ConsoleColor.White));
            }
            for (int i = numCorrectCardsHistorgram.Keys.Max(); i >= 0; i--)
            {
                tt.SetCell(0, i + 1, $"{i} cards".Color(ConsoleColor.White), alignment: HorizontalTextAlignment.Right);
                for (int col = 0; col < rulesIndexesStrs.Length; col++)
                {
                    tt.SetCell(col + 1, i + 1, numCorrectCardsHistorgram.Get(i, null)?.Get(rulesIndexesStrs[col]).NullOr(val => $"{val * 100.0 / numIter:0.0}%".Color(ConsoleColor.Cyan)) ?? "", alignment: HorizontalTextAlignment.Right);
                }
                //Console.WriteLine($"{i} correct cards: {numCorrectCardsHistorgram.Get(i, 0) * 100.0 / numIter:0.0}%");
            }
            tt.WriteToConsole();
            //Console.WriteLine();
            //ConsoleUtil.WriteLine("Distribution of number of wrong cards:".Color(ConsoleColor.White));
            //for (int i = numWrongCardsHistorgram.Keys.Max(); i >= 0; i--)
            //    Console.WriteLine($"{i} wrong cards: {numWrongCardsHistorgram.Get(i, 0) * 100.0 / numIter:0.0}%");
        }
예제 #3
0
파일: Program.cs 프로젝트: rstarkov/AtoZ
        private static void WriteToConsole(IDictionary <string, Highscore> highscores)
        {
            var table = new TextTable {
                ColumnSpacing = 2, DefaultAlignment = HorizontalTextAlignment.Right
            };
            int row = 2;

            foreach (var hs in highscores.OrderBy(kvp => kvp.Key.StartsWith("Recent") ? 1 : 0).ThenBy(kvp => kvp.Key))
            {
                table.SetCell(0, 0, "Name");
                table.SetCell(1, 0, "Any order");
                table.SetCell(2, 0, "Alphabetic", colSpan: 26);

                var best = highscores.Values.Min(h => h.BestAnyOrder);
                table.SetCell(0, row, hs.Key);
                table.SetCell(1, row, toDisplayStr(hs.Value.BestAnyOrder, best));
                for (int i = 0; i < 26; i++)
                {
                    var curChar = (char)('A' + i);
                    best = highscores.Values.Min(h => h.BestAlphabetic[curChar]);
                    table.SetCell(2 + i, 1, curChar.ToString());
                    table.SetCell(2 + i, row, toDisplayStr(hs.Value.BestAlphabetic[curChar], best));
                }
                row++;
            }
            table.WriteToConsole();
        }
예제 #4
0
        static void CountWords()
        {
            var entities = "ensp=\u2002,emsp=\u2003,nbsp=\u00a0,ge=≥,gt=>,lt=<,le=≤,amp=&,shy=\u00ad,mdash=—,trade=™,ohm=Ω,ldquo=“,rdquo=”,horbar=―,rarr=→,uarr=↑,darr=↓,larr=←,times=×"
                           .Split(',')
                           .Select(p => p.Split('='))
                           .ToDictionary(p => $"&{p[0]};", p => p[1]);

            var words =
                new DirectoryInfo(@"D:\c\KTANE\Public\HTML")
                .EnumerateFiles("*.html", SearchOption.TopDirectoryOnly)
                .Where(file => !file.Name.Contains('('))
                .Select(file => File.ReadAllText(file.FullName))
                .Select(text => Regex.Replace(text, @"\A.*(?=<body)", "", RegexOptions.Singleline))
                .Select(text => Regex.Replace(text, @"<style>([^<]*)</style>", "", RegexOptions.Singleline))
                .Select(text => Regex.Replace(text, @"<[^>]+>", "", RegexOptions.Singleline))
                .Select(text => Regex.Replace(text, @"&\w+;", m => entities[m.Value], RegexOptions.Singleline))
                .Select(text => text.Replace("Keep Talking and Nobody Explodes Mod", ""))
                .Select(text => text.Replace("Keep Talking and Nobody Explodes v. 1", ""))
                .SelectMany(text => Regex.Matches(text, @"[-'’\w]+", RegexOptions.Singleline).Cast <Match>())
                .Where(m => m.Value.All(ch => ch >= 'A' && ch <= 'Z'))
                .Select(m => m.Value.ToUpperInvariant())
                //.Where(word => word.Length >= 2)
                .Where(word => Indicator.WellKnown.Concat(new[] { "NLL" }).Contains(word.ToUpperInvariant()))
                .GroupBy(word => word, StringComparer.OrdinalIgnoreCase)
                .ToDictionary(gr => gr.Key, gr => gr.Count(), StringComparer.OrdinalIgnoreCase);

            var tt = new TextTable {
                ColumnSpacing = 2
            };
            var row = 0;

            foreach (var kvp in words.OrderByDescending(p => p.Value).Take(100))
            {
                tt.SetCell(0, row, $"{row + 1}.".ToString().Color(ConsoleColor.Blue), alignment: HorizontalTextAlignment.Right);
                tt.SetCell(1, row, kvp.Value.ToString().Color(ConsoleColor.White), alignment: HorizontalTextAlignment.Right);
                tt.SetCell(2, row, kvp.Key.Color(ConsoleColor.Green));
                tt.SetCell(3, row, new string('█', kvp.Value));
                row++;
            }
            tt.WriteToConsole();
        }
예제 #5
0
        protected override ExecuteResult ExecuteCore()
        {
            var result = new ExecuteResult();

            var volumes = convert(new ManagementObjectSearcher("select * from Win32_Volume").Get());
            var table   = new TextTable();

            table.HeaderRows = 1;
            table.SetCell(0, 0, "Path".Color(ConsoleColor.White));
            table.SetCell(1, 0, "Volume".Color(ConsoleColor.White));
            table.SetCell(2, 0, "Free space".Color(ConsoleColor.White), alignment: HorizontalTextAlignment.Right);
            table.ColumnSpacing = 3;
            int nextRow = 1;

            foreach (var volume in Volumes)
            {
                var volumeName = new string(new char[1024]);
                try
                {
                    GetVolumePathName(volume.Path, volumeName, volumeName.Length);
                    volumeName = volumeName.Substring(0, volumeName.IndexOf('\0'));
                }
                catch
                {
                    throw new Exception($"Unable to retrieve volume name for path {volume.Path}");
                }

                double spaceGb;
                try
                {
                    var vol = volumes.Single(v => (string)v["Name"] == volumeName || (string)v["DeviceID"] == volumeName);
                    volumeName = (string)vol["Name"];
                    spaceGb    = ((ulong)vol["FreeSpace"]) / 1_000_000_000.0;
                }
                catch
                {
                    throw new Exception($"Unable to retrieve free space for volume {volumeName}, path {volume.Path}");
                }

                var status = spaceGb < volume.RedAlertBelowGB ? Status.RedAlert : spaceGb < volume.WarnBelowGB ? Status.Warning : Status.Healthy;
                table.SetCell(0, nextRow, volume.Path);
                table.SetCell(1, nextRow, volumeName);
                table.SetCell(2, nextRow, $"{spaceGb:#,0.0} GB".Color(status.GetConsoleColor()), alignment: HorizontalTextAlignment.Right);
                nextRow++;
                result.UpdateStatus(status);
            }
            result.ConsoleReport += table.ToColoredString();

            return(result);
        }
예제 #6
0
파일: Program.cs 프로젝트: rstarkov/i4c
        /// <summary>
        /// Processes the "benchmark algorithm on all files" command-line command.
        /// </summary>
        private static void command_Benchmark(string algName, RVariant[] algArgs)
        {
            WaitFormShow("benchmarking...");

            Dictionary <string, Compressor> compressors = new Dictionary <string, Compressor>();

            foreach (var file in Directory.GetFiles(".", "*.png"))
            {
                compressors.Add(file, GetCompressor(algName));
            }

            // Queue all jobs...
            foreach (var file in compressors.Keys)
            {
                Compressor compr = compressors[file];
                compr.Configure(algArgs);
                compr.CanonicalFileName = Path.GetFileNameWithoutExtension(file);
                string sourcePath = file;
                string destDir    = PathUtil.AppPathCombine("i4c-output", "benchmark.{0},{1}".Fmt(algName, compr.ConfigString), compr.CanonicalFileName);
                string destFile   = "{0}.{1},{2}.i4c".Fmt(compr.CanonicalFileName, algName, compr.ConfigString);

                Func <Compressor, string, string, string, WaitCallback> makeCallback =
                    (v1, v2, v3, v4) => (dummy2 => CompressFile(v1, v2, v3, v4));
                ThreadPool.QueueUserWorkItem(makeCallback(compr, sourcePath, destDir, destFile));
            }
            // ...and wait until they're finished.
            int worker = 0, dummy;

            while (worker < Environment.ProcessorCount)
            {
                Thread.Sleep(200);
                ThreadPool.GetAvailableThreads(out worker, out dummy);
            }

            // Compute stats totals
            Dictionary <string, double> totals = new Dictionary <string, double>();

            foreach (var file in compressors.Keys)
            {
                var counters = compressors[file].Counters;
                foreach (var key in counters.Keys)
                {
                    if (totals.ContainsKey(key))
                    {
                        totals[key] += counters[key];
                    }
                    else
                    {
                        totals.Add(key, counters[key]);
                    }
                }
            }

            // Write stats totals to a text file
            TextTable table = new TextTable {
                ColumnSpacing = 3, MaxWidth = int.MaxValue, DefaultAlignment = HorizontalTextAlignment.Right
            };

            table.SetCell(1, 0, "TOTAL");
            int colnum = 2;
            int rownum = 2;

            foreach (var str in compressors.Values.Select(val => val.CanonicalFileName).Order())
            {
                table.SetCell(colnum++, 0, str);
            }
            int indent_prev = 0;

            foreach (var key in totals.Keys.Order())
            {
                int indent = 4 * key.ToCharArray().Count(c => c == '|');
                if (indent < indent_prev)
                {
                    rownum++;
                }
                indent_prev = indent;
                table.SetCell(0, rownum, new string(' ', indent) + key.Split('|').Last(), alignment: HorizontalTextAlignment.Left);
                table.SetCell(1, rownum, Math.Round(totals[key], 3).ToString("#,0"));
                colnum = 2;
                foreach (var compr in compressors.Values.OrderBy(c => c.CanonicalFileName))
                {
                    if (compr.Counters.ContainsKey(key))
                    {
                        table.SetCell(colnum++, rownum, Math.Round(compr.Counters[key], 3).ToString("#,0"));
                    }
                    else
                    {
                        table.SetCell(colnum++, rownum, "N/A");
                    }
                }
                rownum++;
            }
            File.WriteAllText(PathUtil.AppPathCombine("i4c-output", "benchmark.{0},{1}.txt".Fmt(algName, compressors.Values.First().ConfigString)), table.ToString());

            WaitFormHide();
        }
예제 #7
0
        public static void RunSimulations()
        {
            const int numIterations = 100000;

            var astrologyElements = new[] { "Fire", "Water", "Earth", "Air" };
            var astrologyPlanets  = new[] { "Sun", "Jupiter", "Moon", "Saturn", "Mercury", "Uranus", "Venus", "Neptune", "Mars", "Pluto" };
            var astrologyZodiacs  = new[] { "Aries", "Leo", "Sagittarius", "Taurus", "Virgo", "Capricorn", "Gemini", "Libra", "Aquarius", "Cancer", "Scorpio", "Pisces" };

            var yes = new[] { "Yes" };

            var blindMazeColorNames = "Red,Green,White,Gray,Yellow".Split(',');

            var simulatables = Ut.NewArray(
                new Simulatable
            {
                Active    = false,
                Name      = "Connection Check",
                GetResult = ew =>
                {
                    var numbers = Enumerable.Range(0, 8).Select(_ => Rnd.Next(1, 9)).ToArray();
                    return(Ut.NewArray(
                               numbers.Distinct().Count() == 8 ? "1. all distinct" :
                               numbers.Count(c => c == 1) > 1 ? "2. more than one “1”" :
                               numbers.Count(c => c == 7) > 1 ? "3. more than one “7”" :
                               numbers.Count(c => c == 2) >= 3 ? "4. at least three “2”s" :
                               numbers.Count(c => c == 5) == 0 ? "5. no “5”s" :
                               numbers.Count(c => c == 8) == 2 ? "6. exactly two “8”s" :
                               ew.GetNumBatteries().Apply(bs => bs > 6 || bs == 0) ? "7. more than 6 or no batteries" :
                               "8. count the batteries"));
                }
            },
                new Simulatable
            {
                Active    = false,
                Name      = "Laundry: 4/2+BOB (“unicorn”)",
                GetResult = ew => ew.GetNumAABatteries() == 4 && ew.GetNumDBatteries() == 0 && ew.HasLitIndicator("BOB") ? yes : null
            },
                new Simulatable
            {
                Active    = false,
                Name      = "Lettered Keys",
                GetResult = ew =>
                {
                    var number = Rnd.Next(0, 100);
                    return(Ut.NewArray(
                               number == 69 ? "1. 69 → D" :
                               number % 6 == 0 ? "2. divisible by 6 → A" :
                               ew.GetNumBatteries() >= 2 && number % 3 == 0 ? "3. ≥ 2 batteries and divisible by 3 → B" :
                               ew.SerialNumber.Any("CE3".Contains) ? (number >= 22 && number <= 79 ? "4. C, E, 3 & 22 ≤ n ≤ 79 → B" : "5. C, E, 3 → C") :
                               number < 46 ? "6. n < 46 → D" : "7. otherwise → A"));
                }
            },
                new Simulatable
            {
                Active    = false,
                Name      = "Astrology",
                GetResult = ew =>
                {
                    var planet  = Rnd.Next(astrologyPlanets.Length);
                    var zodiac  = Rnd.Next(astrologyZodiacs.Length);
                    var element = Rnd.Next(astrologyElements.Length);

                    var elemPlanet = new[, ] {
                        { 0, 0, 1, -1, 0, 1, -2, 2, 0, -1 },
                        { -2, 0, -1, 0, 2, 0, -2, 2, 0, 1 },
                        { -1, -1, 0, -1, 1, 2, 0, 2, 1, -2 },
                        { -1, 2, -1, 0, -2, -1, 0, 2, -2, 2 }
                    };
                    var elemZodiac = new[, ] {
                        { 1, 0, -1, 0, 0, 2, 2, 0, 1, 0, 1, 0 },
                        { 2, 2, -1, 2, -1, -1, -2, 1, 2, 0, 0, 2 },
                        { -2, -1, 0, 0, 1, 0, 1, 2, -1, -2, 1, 1 },
                        { 1, 1, -2, -2, 2, 0, -1, 1, 0, 0, -1, -1 }
                    };
                    var planetZodiac = new[, ] {
                        { -1, -1, 2, 0, -1, 0, -1, 1, 0, 0, -2, -2 },
                        { -2, 0, 1, 0, 2, 0, -1, 1, 2, 0, 1, 0 },
                        { -2, -2, -1, -1, 1, -1, 0, -2, 0, 0, -1, 1 },
                        { -2, 2, -2, 0, 0, 1, -1, 0, 2, -2, -1, 1 },
                        { -2, 0, -1, -2, -2, -2, -1, 1, 1, 1, 0, -1 },
                        { -1, -2, 1, -1, 0, 0, 0, 1, 0, -1, 2, 0 },
                        { -1, -1, 0, 0, 1, 1, 0, 0, 0, 0, -1, -1 },
                        { -1, 2, 0, 0, 1, -2, 1, 0, 2, -1, 1, 0 },
                        { 1, 0, 2, 1, -1, 1, 1, 1, 0, -2, 2, 0 },
                        { -1, 0, 0, -1, -2, 1, 2, 1, 1, 0, 0, -1 }
                    };

                    var omen = new[] { astrologyPlanets[planet], astrologyZodiacs[zodiac], astrologyElements[element] }.Sum(str => str.Any(ew.SerialNumber.Contains) ? 1 : -1);
                    omen    += elemPlanet[element, planet] + elemZodiac[element, zodiac] + planetZodiac[planet, zodiac];
                    return(omen == 0 ? new[] { "No Omen" } : omen > 0 ? new[] { "Good Omen", omen.ToString() } : new[] { "Poor Omen", (-omen).ToString() });
                }
            },
                new Simulatable
            {
                Active    = false,
                Name      = "Plumbing",
                GetResult = ew =>
                {
                    // Plumbing: most inputs and outputs
                    var redInput =
                        // For: Serial contains a '1'
                        +(ew.SerialNumber.Contains('1') ? 1 : 0)
                        // For: Exactly 1 RJ45 port
                        + (ew.GetNumPorts(PortType.RJ45) == 1 ? 1 : 0)
                        // Against: Any duplicate ports
                        - (ew.HasDuplicatePorts() ? 1 : 0)
                        // Against: Any duplicate ew.SerialNumber characters
                        - (ew.SerialNumber.Order().SelectConsecutivePairs(false, (c1, c2) => c1 == c2).Any() ? 1 : 0)
                        > 0;

                    var yellowInput =
                        // For: Serial contains a '2'
                        +(ew.SerialNumber.Contains('2') ? 1 : 0)
                        // For: One or more Stereo RCA ports
                        + (ew.GetNumPorts(PortType.StereoRCA) > 0 ? 1 : 0)
                        // Against: No duplicate ports
                        - (ew.HasDuplicatePorts() ? 0 : 1)
                        // Against: Serial contains a '1' or 'L'
                        - (ew.SerialNumber.Contains('1') || ew.SerialNumber.Contains('L') ? 1 : 0)
                        > 0;

                    var greenInput =
                        // For: Serial contains 3 or more numbers
                        +(ew.SerialNumber.Count(ch => ch >= '0' && ch <= '9') >= 3 ? 1 : 0)
                        // For: One or more DVI-D ports
                        + (ew.GetNumPorts(PortType.DVI) > 0 ? 1 : 0)
                        // Against: Red Input is inactive
                        - (redInput ? 0 : 1)
                        // Against: Yellow Input is inactive
                        - (yellowInput ? 0 : 1)
                        > 0;

                    var blueInput =
                        // Note: Always active if all other inputs are inactive
                        (!redInput && !yellowInput && !greenInput) || (
                            // For: At least 4 unique ports
                            (ew.GetNumPortTypes() >= 4 ? 1 : 0)
                            // For: At least 4 batteries
                            + (ew.GetNumBatteries() >= 4 ? 1 : 0)
                            // Against: No ports
                            - (ew.GetPorts().Any() ? 0 : 1)
                            // Against: No batteries
                            - (ew.GetNumBatteries() == 0 ? 1 : 0)
                            > 0
                            );

                    var redOutput =
                        // For: One or more Serial ports
                        (ew.GetNumPorts(PortType.Serial) > 0 ? 1 : 0)
                        // For: Exactly one battery
                        + (ew.GetNumBatteries() == 1 ? 1 : 0)
                        // Against: Serial contains more than 2 numbers
                        - (ew.SerialNumber.Count(ch => ch >= '0' && ch <= '9') >= 3 ? 1 : 0)
                        // Against: More than 2 inputs are active
                        - ((redInput ? 1 : 0) + (blueInput ? 1 : 0) + (greenInput ? 1 : 0) + (yellowInput ? 1 : 0) > 2 ? 1 : 0)
                        > 0;

                    var yellowOutput =
                        // For: Any duplicate ports
                        (ew.HasDuplicatePorts() ? 1 : 0)
                        // For: Serial contains a '4' or '8'
                        + (ew.SerialNumber.Contains('4') || ew.SerialNumber.Contains('8') ? 1 : 0)
                        // Against: Serial doesn't contain a '2'
                        - (ew.SerialNumber.Contains('2') ? 0 : 1)
                        // Against: Green Input is active
                        - (greenInput ? 1 : 0)
                        > 0;

                    var greenOutput =
                        // For: Exactly 3 inputs are active
                        ((redInput ? 1 : 0) + (blueInput ? 1 : 0) + (greenInput ? 1 : 0) + (yellowInput ? 1 : 0) == 3 ? 1 : 0)
                        // For: Exactly 3 ports are present
                        + (ew.GetNumPorts() == 3 ? 1 : 0)
                        // Against: Less than 3 ports are present
                        - (ew.GetNumPorts() < 3 ? 1 : 0)
                        // Against: Serial contains more than 3 numbers
                        - (ew.SerialNumberDigits().Count() > 3 ? 1 : 0)
                        > 0;

                    var blueOutput =
                        // Note: Always active if all other outputs are inactive
                        (!redOutput && !greenOutput && !yellowOutput) ||
                        // For: All inputs are active
                        +((redInput && greenInput && yellowInput && blueInput) ? 1 : 0)
                        // For: Any other output is inactive
                        + (!redOutput || !yellowOutput || !greenOutput ? 1 : 0)
                        // Against: Less than 2 batteries
                        - (ew.GetNumBatteries() < 2 ? 1 : 0)
                        // Against: No Parallel port
                        - (ew.GetNumPorts(PortType.Parallel) == 0 ? 1 : 0)
                        > 0;

                    var numInputs  = (redInput ? 1 : 0) + (blueInput ? 1 : 0) + (greenInput ? 1 : 0) + (yellowInput ? 1 : 0);
                    var numOutputs = (redOutput ? 1 : 0) + (blueOutput ? 1 : 0) + (greenOutput ? 1 : 0) + (yellowOutput ? 1 : 0);

                    return(Ut.NewArray(
                               //$"{numInputs} inputs",
                               //$"{numOutputs} outputs"
                               new[] {
                        redInput ? "Red in" : null, yellowInput ? "Yellow in" : null, greenInput ? "Green in" : null, blueInput ? "Blue in" : null,
                        redOutput ? "Red out" : null, yellowOutput ? "Yellow out" : null, greenOutput ? "Green out" : null, blueOutput ? "Blue out" : null
                    }
                               .Where(s => s != null).JoinString(", ")
                               ));
                }
            },
                new Simulatable
            {
                Active    = false,
                Name      = "Chess",
                GetResult = ew => new[] { Chess.GetSolution(ew.SerialNumber.Last() % 2 != 0, out _, out _)[6] }
            },
                new Simulatable
            {
                Active    = true,
                Name      = "Blind Maze",
                GetResult = ew =>
                {
                    // Colors of the N/S/W/E buttons
                    var cols = new[] { Rnd.Next(0, 5), Rnd.Next(0, 5), Rnd.Next(0, 5), Rnd.Next(0, 5) };

                    // 0 = Red
                    // 1 = Green
                    // 2 = White
                    // 3 = Gray
                    // 4 = Yellow

                    // If there are at least two red buttons,
                    if (cols.Count(c => c == 0) >= 2)
                    {
                        // rotate the maze 90 degrees clockwise and then calculate starting position.
                        return new[] { "90", "after" }
                    }
                    ;

                    // Otherwise, if there are at least 5 batteries,
                    if (ew.GetNumBatteries() >= 5)
                    {
                        // calculate starting position and then rotate the maze 90 degrees clockwise.
                        return new[] { "90", "before" }
                    }
                    ;

                    // Otherwise, if there is an IND indicator,
                    if (ew.HasIndicator("IND"))
                    {
                        // rotate the maze 180 degrees and then calculate starting position.
                        return new[] { "180", "after" }
                    }
                    ;

                    // Otherwise, if there are no yellow buttons and at least one red button,
                    if (cols.Count(c => c == 4) == 0 && cols.Count(c => c == 0) > 0)
                    {
                        // rotate your perspective of the maze 90 degrees clockwise and then calculate starting position.
                        return new[] { "270", "after" }
                    }
                    ;

                    // Otherwise, if there are at least 2 types of maze-based modules on the bomb*,
                    if (Rnd.NextDouble() < .25)
                    {
                        // calculate starting position and then rotate the maze 180 degrees clockwise.
                        return new[] { "180", "before" }
                    }
                    ;

                    // Otherwise, if there is at most 1 port type on the bomb,
                    if (ew.GetNumPortTypes() < 2)
                    {
                        // calculate starting position and then rotate your perspective of the maze 90 degrees clockwise.
                        return new[] { "270", "before" }
                    }
                    ;

                    // Otherwise, keep the maze as it is.
                    return(new[] { "0" });
                }
            }
                ).Where(s => s.Active).ToArray();

            var results    = new AutoDictionary <string, SimulatedResult>(str => new SimulatedResult());
            var hundredths = numIterations / 100;

            for (int attempt = 0; attempt < numIterations; attempt++)
            {
                if (attempt % hundredths == 0)
                {
                    Console.Write($"{attempt / hundredths}%\r");
                }

                var edgework = Edgework.Generate();

                foreach (var sim in simulatables)
                {
                    var result = sim.GetResult(edgework);
                    if (result == null)
                    {
                        continue;
                    }
                    var sr = results[sim.Name];
                    for (int i = 0; i < result.Length; i++)
                    {
                        sr = sr.Children[result[i]];
                    }
                    sr.Count++;
                }
            }
            Console.WriteLine("Done");
            Console.WriteLine();

            var tt = new TextTable {
                ColumnSpacing = 2
            };
            var row = 0;

            foreach (var kvp in results)
            {
                tt.SetCell(0, row, kvp.Key.Color(ConsoleColor.White));
                tt.SetCell(1, row, "{0/Cyan:0.####}% (or 1 in {1/Magenta:0}){2}".Color(ConsoleColor.Gray).Fmt(
                               kvp.Value.TotalCount / (double)numIterations * 100,
                               numIterations / (double)kvp.Value.TotalCount,
                               generateTree(kvp.Value, numIterations, skipTop: true)));
                row++;
            }
            tt.WriteToConsole();
            Console.WriteLine();
        }
예제 #8
0
        public static void GenerateData()
        {
            var freqs = new Dictionary <char, int>();

            foreach (var p in _text)
            {
                foreach (var w in p)
                {
                    foreach (var l in w)
                    {
                        freqs.IncSafe(l);
                    }
                }
            }
            ConsoleUtil.WriteParagraphs(freqs.OrderByDescending(kvp => kvp.Value).Select(kvp => $"{kvp.Key}={kvp.Value}").JoinString(", "));

            Console.WriteLine(new string('─', 20));

            var lists = _text.Select(line => line.Select(word => word.Select(x => new List <(int paraIx, int wordIx, int letterIx)>()).ToArray()).ToArray()).ToArray();
            var dic   = new Dictionary <char, List <(int paraIx, int wordIx, int letterIx)> >();

            for (int p = 0; p < 26; p++)
            {
                for (int w = 0; w < 26; w++)
                {
                    if (w != p)
                    {
                        for (int l = 0; l < 26; l++)
                        {
                            if (l != p && l != w)
                            {
                                var(paraIx, wordIx, letterIx, ch) = getPosition(p, w, l);
                                lists[paraIx][wordIx][letterIx].Add((p, w, l));
                                dic.AddSafe(ch, (p, w, l));
                            }
                        }
                    }
                }
            }

            ConsoleUtil.WriteParagraphs(_text.Select((para, paraIx) => para.Select((word, wordIx) => word.Select((ch, chIx) =>
            {
                var num = lists[paraIx][wordIx][chIx].Count / 2;
                return(ch.Color((ConsoleColor)(num % 16), num == 0 ? ConsoleColor.Red : (ConsoleColor)(num / 16)));
            }).JoinColoredString()).JoinColoredString(" ")).JoinColoredString("\n"));
            ConsoleUtil.WriteLine("{0} paragraphs. Unused letters = {1}".Color(null)
                                  .Fmt(_text.Length, lists.Sum(one => one.Sum(two => two.Count(three => three.Count == 0))).Apply(x => x.ToString().Color(x == 0 ? ConsoleColor.Green : ConsoleColor.Magenta))));

            Utils.ReplaceInFile(@"D:\c\KTANE\SimonSends\Assets\SimonSendsModule.cs", "/*MANUAL*/", "/*!MANUAL*/", $@"@""{_text.Select(para => para.JoinString(" ")).JoinString("|")}""");

            const int iterations = 1000000;

            // How many times does each combo occur? Sum of the values is equal to iterations.
            var comboStats = new Dictionary <string, int>();

            // How many times does each letter (A–Z) occur? Sum is greater than iterations.
            var letterStats = Ut.NewArray(3, _ => new Dictionary <char, int>());

            // How many times does each solution length occur?
            var lengthStats = new Dictionary <int, int>();

            for (int iter = 0; iter < iterations; iter++)
            {
                var available = Enumerable.Range(0, 26).ToList().Shuffle();
                var r         = available[0];
                var g         = available[1];
                var b         = available[2];

                var(_, _, _, newR) = getPosition(b, g, r);
                var(_, _, _, newG) = getPosition(r, b, g);
                var(_, _, _, newB) = getPosition(g, r, b);

                var rMorse = constructMorse(newR);
                var gMorse = constructMorse(newG);
                var bMorse = constructMorse(newB);
                var combo  = Enumerable.Range(0, Ut.Max(rMorse.Length, gMorse.Length, bMorse.Length))
                             .Select(i =>
                {
                    var isR = i >= rMorse.Length ? false : rMorse[i] == '#';
                    var isG = i >= gMorse.Length ? false : gMorse[i] == '#';
                    var isB = i >= bMorse.Length ? false : bMorse[i] == '#';
                    return("KBGCRMYW"[(isB ? 1 : 0) + (isG ? 2 : 0) + (isR ? 4 : 0)]);
                })
                             .JoinString();
                comboStats.IncSafe(combo);
                letterStats[0].IncSafe(newR);
                letterStats[1].IncSafe(newG);
                letterStats[2].IncSafe(newB);
                lengthStats.IncSafe(combo.Length);
            }

            Console.WriteLine(comboStats.Count);
            foreach (var kvp in comboStats.OrderByDescending(p => p.Value).Take(10))
            {
                Console.WriteLine($"{kvp.Key,13} = {100 * kvp.Value / (double) iterations:0.##}%");
            }
            Console.WriteLine("---");
            var tt = new TextTable {
                ColumnSpacing = 2
            };

            for (int i = 0; i < 3; i++)
            {
                tt.SetCell(i, 0, letterStats[i]
                           .OrderByDescending(p => p.Value)
                           .Select(kvp => "{0} = {1,6:0.00}% {2}".Color(null).Fmt(kvp.Key.Color(new[] { ConsoleColor.Red, ConsoleColor.Green, ConsoleColor.Blue }[i]), 100 * kvp.Value / (double)iterations, new string('█', (200 * kvp.Value + iterations / 2) / iterations)))
                           .JoinColoredString("\n")
                           .Replace(" ", "\u00a0"));
            }
            tt.WriteToConsole();
            Console.WriteLine("---");
            foreach (var kvp in lengthStats.OrderBy(p => p.Key))
            {
                Console.WriteLine($"{kvp.Key,2} = {100 * kvp.Value / (double) iterations,6:0.00}% {new string('█', (100 * kvp.Value + iterations / 2) / iterations)}");
            }
        }
예제 #9
0
        private static void SetCell(TextTable tt, int col, int row, Dictionary <string, string> items)
        {
            string str = null;

            if (items.Values.Distinct().Count() == 1)
            {
                str = items.Values.First();
            }
            else
            {
                // Try numbers
                var strs1 = new List <string>();
                for (char n = '1'; n <= '3'; n++)
                {
                    var tItems = items.Where(p => p.Key.StartsWith(n)).ToArray();
                    if ("ASDF".All(ch => items.ContainsKey(n.ToString() + ch)))
                    {
                        var biggestGroup = tItems.GroupBy(p => p.Value).MaxElement(g => g.Count());
                        if (biggestGroup.Count() == 1)
                        {
                            biggestGroup = null;
                        }
                        foreach (var tItem in tItems)
                        {
                            if (biggestGroup == null || !biggestGroup.Any(p => p.Key == tItem.Key))
                            {
                                strs1.Add($"{tItem.Key}={tItem.Value}");
                            }
                        }
                        if (biggestGroup != null)
                        {
                            strs1.Add($"{n}={biggestGroup.First().Value}");
                        }
                    }
                    else
                    {
                        strs1.AddRange(tItems.Select(p => $"{p.Key}={p.Value}"));
                    }
                }

                // Try letters
                var strs2 = new List <string>();
                foreach (char l in "ASDF")
                {
                    var tItems = items.Where(p => p.Key.EndsWith(l)).ToArray();
                    if ("123".All(ch => items.ContainsKey(ch + l.ToString())))
                    {
                        var biggestGroup = tItems.GroupBy(p => p.Value).MaxElement(g => g.Count());
                        if (biggestGroup.Count() == 1)
                        {
                            biggestGroup = null;
                        }
                        foreach (var tItem in tItems)
                        {
                            if (biggestGroup == null || !biggestGroup.Any(p => p.Key == tItem.Key))
                            {
                                strs2.Add($"{tItem.Key}={tItem.Value}");
                            }
                        }
                        if (biggestGroup != null)
                        {
                            strs2.Add($"{l}={biggestGroup.First().Value}");
                        }
                    }
                    else
                    {
                        strs2.AddRange(tItems.Select(p => $"{p.Key}={p.Value}"));
                    }
                }

                str = (strs1.Count > strs2.Count ? strs2 : strs1).JoinString("\n");
            }
            tt.SetCell(col, row, str);
        }
예제 #10
0
        public static void Simulations()
        {
            const int iterations    = 100000;
            const int quadrantCount = 5;

            var getQuadrantCounts = Ut.Lambda((bool[][] arr) =>
            {
                var qCounts = new int[4];
                for (int x = 0; x < 8; x++)
                {
                    for (int y = 0; y < 8; y++)
                    {
                        if (arr[x][y])
                        {
                            qCounts[(y / 4) * 2 + (x / 4)]++;
                        }
                    }
                }
                return(qCounts);
            });

            var quadrantCountRule = Ut.Lambda((bool white) => new Tuple <string, Func <bool[][], Edgework, int> >(
                                                  $"Exactly one quadrant has {quadrantCount} or fewer {(white ? "white" : "black")} pixels ⇒ number of {(white ? "white" : "black")} pixels in the other 3 quadrants",
                                                  (arr, edgework) =>
            {
                var qCounts = getQuadrantCounts(arr);
                if ((white ? qCounts.Count(sum => sum <= quadrantCount) : qCounts.Count(sum => sum >= (16 - quadrantCount))) != 1)
                {
                    return(0);
                }
                var qIx = (white ? qCounts.IndexOf(sum => sum <= quadrantCount) : qCounts.IndexOf(sum => sum >= (16 - quadrantCount))) + 1;
                return((qCounts.Where((sum, ix) => ix != qIx).Sum() + 3) % 4 + 1);
            }));

            var totalCountRule = Ut.Lambda((int num, bool white) => new Tuple <string, Func <bool[][], Edgework, int> >(
                                               $"The entire bitmap has {num} or more {(white ? "white" : "black")} pixels ⇒ number of {(white ? "white" : "black")} pixels",
                                               (arr, edgework) =>
            {
                var sum = 0;
                for (int x = 0; x < 8; x++)
                {
                    for (int y = 0; y < 8; y++)
                    {
                        sum += (arr[x][y] ^ white) ? 0 : 1;
                    }
                }
                if (sum >= num)
                {
                    return(((sum + 3) % 4) + 1);
                }
                return(0);
            }));

            var rowColumnRule = new Tuple <string, Func <bool[][], Edgework, int> >(
                "Exactly one row or column is completely white or completely black ⇒ x- or y-coordinate",
                (arr, edgework) =>
            {
                int answer = 0;
                for (int x = 0; x < 8; x++)
                {
                    var isWhite = arr[x][0];
                    for (int y = 1; y < 8; y++)
                    {
                        if (arr[x][y] != isWhite)
                        {
                            goto next;
                        }
                    }

                    if (answer != 0)
                    {
                        return(0);
                    }
                    // The coordinate is 0-based, but the answer needs to be 1-based.
                    answer = (x % 4) + 1;

                    next:;
                }
                for (int y = 0; y < 8; y++)
                {
                    var isWhite = arr[0][y];
                    for (int x = 1; x < 8; x++)
                    {
                        if (arr[x][y] != isWhite)
                        {
                            goto next;
                        }
                    }

                    if (answer != 0)
                    {
                        return(0);
                    }
                    // The coordinate is 0-based, but the answer needs to be 1-based.
                    answer = (y % 4) + 1;

                    next:;
                }
                return(answer);
            });

            var squareRule = new Tuple <string, Func <bool[][], Edgework, int> >(
                "There is a 3×3 square that is completely white or completely black ⇒ x-coordinate of center of first in reading order",
                (arr, edgework) =>
            {
                for (int x = 1; x < 7; x++)
                {
                    for (int y = 1; y < 7; y++)
                    {
                        var isWhite = arr[x][y];
                        for (int xx = -1; xx < 2; xx++)
                        {
                            for (int yy = -1; yy < 2; yy++)
                            {
                                if (arr[x + xx][y + yy] != isWhite)
                                {
                                    goto next;
                                }
                            }
                        }
                        // x is 0-based, but the answer needs to be 1-based.
                        return((x % 4) + 1);

                        next:;
                    }
                }
                return(0);
            });

            var quadrantMajorityRule = Ut.Lambda((string name, Func <int, int, Edgework, bool> compare, Func <int, int, Edgework, bool[][], int> getAnswer) => new Tuple <string, Func <bool[][], Edgework, int> >(
                                                     name,
                                                     (arr, widgets) =>
            {
                var quadrantCounts = new int[4];
                for (int x = 0; x < 8; x++)
                {
                    for (int y = 0; y < 8; y++)
                    {
                        if (arr[x][y])
                        {
                            quadrantCounts[(x / 4) * 2 + (y / 4)]++;
                        }
                    }
                }
                var w = quadrantCounts.Count(q => q > 8);
                var b = quadrantCounts.Count(q => q < 8);
                return(compare(b, w, widgets) ? ((getAnswer(b, w, widgets, arr) + 3) % 4) + 1 : 0);
            }));

            var rules = Ut.NewArray(
                quadrantCountRule(true),
                quadrantMajorityRule("There are as many mostly-white quadrants as there are lit indicators ⇒ number of batteries", (b, w, widgets) => w == widgets.GetNumLitIndicators(), (b, w, widgets, arr) => widgets.GetNumBatteries()),
                rowColumnRule,
                quadrantMajorityRule("There are fewer mostly-white quadrants than mostly-black quadrants ⇒ number of mostly-black quadrants", (b, w, widgets) => w < b, (b, w, widgets, arr) => b),
                totalCountRule(36, true),
                quadrantMajorityRule("There are more mostly-white quadrants than mostly-black quadrants ⇒ smallest number of black in any quadrant", (b, w, widgets) => w > b, (b, w, widgets, arr) => 16 - getQuadrantCounts(arr).Max()),
                quadrantCountRule(false),
                quadrantMajorityRule("There are as many mostly-black quadrants as there are unlit indicators ⇒ number of ports", (b, w, widgets) => b == widgets.GetNumUnlitIndicators(), (b, w, widgets, arr) => widgets.GetNumPorts()),
                squareRule,
                quadrantMajorityRule("There are as many mostly-white quadrants as mostly-black quadrants ⇒ first numeric digit of the serial number", (b, w, widgets) => w == b, (b, w, widgets, arr) => Rnd.Next(0, 10)));

            var counts = new int[rules.Length, 4];

            for (int iter = 0; iter < iterations; iter++)
            {
                var edgework  = Edgework.Generate();
                var bitmap    = Ut.NewArray(8, 8, (_, __) => Rnd.Next(0, 2) == 0);
                var startRule = Rnd.Next(0, rules.Length);

                var    answer = 0;
                string rule;
                int    ruleIndex;
                for (int r = 0; r < rules.Length; r++)
                {
                    ruleIndex = (r + startRule) % rules.Length;
                    var tup = rules[ruleIndex];
                    answer = tup.Item2(bitmap, edgework);
                    if (answer != 0)
                    {
                        rule = tup.Item1;
                        goto found;
                    }
                }
                Console.WriteLine(rules.Select(r => r.Item2(bitmap, edgework)).JoinString(", "));
                System.Diagnostics.Debugger.Break();
                break;

                found :;
                counts[ruleIndex, answer - 1]++;
            }

            var tt = new TextTable {
                ColumnSpacing = 2
            };
            var ruleCounts = new int[rules.Length];

            for (int a = 0; a < 4; a++)
            {
                tt.SetCell(a + 1, 0, (a + 1).ToString().Color(ConsoleColor.White), alignment: HorizontalTextAlignment.Right);
                tt.SetCell(a + 1, rules.Length + 1, ((Enumerable.Range(0, rules.Length).Sum(r => counts[r, a]) * 100 / (double)iterations).ToString("0.0") + "%").Color(ConsoleColor.Green), alignment: HorizontalTextAlignment.Right);
            }

            for (int r = 0; r < rules.Length; r++)
            {
                tt.SetCell(0, r + 1, rules[r].Item1.Color(ConsoleColor.Cyan).Apply(s => s.ColorSubstring(s.IndexOf('⇒'), ConsoleColor.DarkCyan)), alignment: HorizontalTextAlignment.Right);
                for (int a = 0; a < 4; a++)
                {
                    tt.SetCell(a + 1, r + 1, ((counts[r, a] * 100 / (double)iterations).ToString("0.0") + "%").Color(ConsoleColor.Magenta), alignment: HorizontalTextAlignment.Right);
                }
                tt.SetCell(5, r + 1, ((Enumerable.Range(0, 4).Sum(a => counts[r, a]) * 100 / (double)iterations).ToString("0.0") + "%").Color(ConsoleColor.White), alignment: HorizontalTextAlignment.Right);
                ruleCounts[r] += Enumerable.Range(0, 4).Sum(a => counts[r, a]);
            }

            tt.WriteToConsole();
            Console.WriteLine();
            ConsoleUtil.WriteLine("Ratio of most likely to least likely rule: {0/White:0.0}".Color(ConsoleColor.White).Fmt(ruleCounts.Max() / (double)ruleCounts.Min()));
        }
예제 #11
0
        public static void RunStatistics()
        {
            var opinions = new List <int> [6];

            for (int i = 0; i < 6; i++)
            {
                opinions[i] = new List <int>();
            }
            const int iterations = 1000000;

            for (int iter = 0; iter < iterations; iter++)
            {
                var edgework = Edgework.Generate(5, 5);
                var i        = edgework.GetNumIndicators();
                var b        = edgework.GetNumBatteries();
                var m        = Rnd.Next(7, 16);
                var h        = edgework.GetNumBatteryHolders();
                var f        = Rnd.NextDouble() < .02 ? 1 : 0;
                var p        = edgework.GetNumPorts();
                var l        = edgework.GetNumPortPlates();
                var s        = edgework.SerialNumberDigits().Sum();

                opinions[0].Add((h * f - l * l) + 20 * b);
                opinions[1].Add(s * p - b * b * b);
                opinions[2].Add(m + 3 * (i + p) - f * b);
                opinions[3].Add(i * (20 + m) - p * l);
                opinions[4].Add(p * (l * b + 3) + l + b - s);
                opinions[5].Add(h * h * h + l * l + f * f * f * f - m);
            }

            var tt = new TextTable {
                ColumnSpacing = 2
            };

            tt.SetCell(0, 0, "Faction");
            tt.SetCell(1, 0, "Mean", alignment: HorizontalTextAlignment.Right);
            tt.SetCell(2, 0, "Variance", alignment: HorizontalTextAlignment.Right);
            tt.SetCell(3, 0, "Stddev", alignment: HorizontalTextAlignment.Right);
            tt.SetCell(4, 0, "Min", alignment: HorizontalTextAlignment.Right);
            tt.SetCell(5, 0, "Max", alignment: HorizontalTextAlignment.Right);
            for (int i = 0; i < 6; i++)
            {
                tt.SetCell(0, i + 1, "red,blue,yellow,green,purple,orange".Split(',')[i]);
                var mean     = (double)opinions[i].Sum() / iterations;
                var variance = opinions[i].Sum(o => (o - mean) * (o - mean)) / iterations;
                tt.SetCell(1, i + 1, $"{mean:0.0}", alignment: HorizontalTextAlignment.Right);
                tt.SetCell(2, i + 1, $"{variance:0.0}", alignment: HorizontalTextAlignment.Right);
                tt.SetCell(3, i + 1, $"{Math.Sqrt(variance):0.0}", alignment: HorizontalTextAlignment.Right);
                tt.SetCell(4, i + 1, opinions[i].Min().ToString(), alignment: HorizontalTextAlignment.Right);
                tt.SetCell(5, i + 1, opinions[i].Max().ToString(), alignment: HorizontalTextAlignment.Right);
            }
            tt.WriteToConsole();
        }