Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add note in readme to say all solutions exist now #367

Closed
wants to merge 1 commit into from

Conversation

joshgrib
Copy link
Contributor

@joshgrib joshgrib commented Jan 3, 2022

I was wondering if there was any games that hadn't been implemented yet and it appears there are not. I wrote a little JS script to check (below), but figured there should be a note in the readme so other people don't spent time trying to see what's left to do.

/**
 * Program to find games that are missing solutions in a given language
 * 
 * Scan each game folder, check for a folder for each language, and also make
 * sure there's at least one file of the expected extension and not just a
 * readme or something
 */

const fs = require('fs');
const glob = require('glob');

// relative path to the repository root
const rootPath = '.';

const languages = [
    { name: 'csharp', extension: 'cs' },
    { name: 'java', extension: 'java' },
    { name: 'javascript', extension: 'js' },
    { name: 'pascal', extension: 'pas' },
    { name: 'perl', extension: 'pl' },
    { name: 'python', extension: 'py' },
    { name: 'ruby', extension: 'rb' },
    { name: 'vbnet', extension: 'vb' },
];

const missing = [];

fs.readdirSync('.', { withFileTypes: true })
    .filter(dirEntry => dirEntry.isDirectory())
    .filter(dirEntry => !['.git', 'node_modules'].includes(dirEntry.name))
    .forEach(dirEntry => {
        const { name: puzzle } = dirEntry;
        languages.map(({ name: language, extension }) => {
            if (!fs.existsSync(`${rootPath}/${puzzle}/${language}`)) {
                missing.push(`No ${language} folder for ${puzzle}`);
            } else {
                // check for one file with the right extension
                glob(`${rootPath}/${puzzle}/${language}/**/*.${extension}`, (err, matches) => {
                    if (err) {
                        console.error(err);
                    } else {
                        if (matches.length === 0) {
                            missing.push(`No ${extension} files for ${puzzle}/${language}`);
                        }
                    }
                });
            }
        });
    });

if (missing.length === 0) {
    console.log('All games have solutions for all languages');
} else {
    console.log(`Missing solutions for ${missing.length} games:`);
    missing.forEach(msg => console.log(msg));
}

@joshgrib
Copy link
Contributor Author

joshgrib commented Jan 3, 2022

Wasn't sure what the wording should be so feel free to change, I just wanted something to let people know that there aren't any games that are missing a language implementation

@coding-horror
Copy link
Owner

are we sure this is correct? I clicked through on a random folder, 04_Awari and I don't see

  • pascal version
  • perl version
  • ruby version
  • vb.net version

@joshgrib joshgrib mentioned this pull request Jan 3, 2022
@joshgrib
Copy link
Contributor Author

joshgrib commented Jan 3, 2022

Ah yep this can definitely be closed - I had an async bug causing it to check if an array is empty before anything had a chance to get inserted, and the languages I was spot-checking the most (javascript and python) seem to also be the most implemented.

Here's the updated script with the bug fixed and some additional counts by game/language. I'll open a new PR to include this script in the repo, but feel free to reject it too for whatever reason, just seems like it could be useful

/**
 * Program to find games that are missing solutions in a given language
 * 
 * Scan each game folder, check for a folder for each language, and also make
 * sure there's at least one file of the expected extension and not just a
 * readme or something
 */

const fs = require('fs');
const glob = require('glob');

// relative path to the repository root
const ROOT_PATH = '.';

const languages = [
    { name: 'csharp', extension: 'cs' },
    { name: 'java', extension: 'java' },
    { name: 'javascript', extension: 'js' },
    { name: 'pascal', extension: 'pas' },
    { name: 'perl', extension: 'pl' },
    { name: 'python', extension: 'py' },
    { name: 'ruby', extension: 'rb' },
    { name: 'vbnet', extension: 'vb' },
];

const getFilesRecursive = async (path, extension) => {
    return new Promise((resolve, reject) => {
        glob(`${path}/**/*.${extension}`, (err, matches) => {
            if (err) {
                reject(err);
            }
            resolve(matches);
        });
    });
}

const getPuzzleFolders = () => {
    return fs.readdirSync(ROOT_PATH, { withFileTypes: true })
        .filter(dirEntry => dirEntry.isDirectory())
        .filter(dirEntry => !['.git', 'node_modules'].includes(dirEntry.name))
        .map(dirEntry => dirEntry.name);
}

(async () => {
    let missing = [];
    let missingGames = {};
    let missingLanguageCounts = {};
    const puzzles = getPuzzleFolders();
    for (const puzzle of puzzles) {
        for (const { name: language, extension } of languages) {
            const files = await getFilesRecursive(`${ROOT_PATH}/${puzzle}/${language}`, extension);
            if (files.length === 0) {
                missing.push(`${puzzle}/${language}`);
                if (!missingGames[puzzle]) {
                    missingGames[puzzle] = [];
                }
                if (!missingLanguageCounts[language]) {
                    missingLanguageCounts[language] = 0;
                }
                missingGames[puzzle].push(language);
                missingLanguageCounts[language]++;
            }
        }
    }
    if (missing.length === 0) {
        console.log('All games have solutions for all languages')
    } else {
        console.log(`Missing ${missing.length} implementations:`);

        console.log(`\nMissing languages by game:`);
        for (const [puzzle, languages] of Object.entries(missingGames)) {
            console.log(`${puzzle}: ${languages.join(', ')}`);
        }

        console.log(`\nBy language:`);
        for (const [language, count] of Object.entries(missingLanguageCounts)) {
            console.log(`${language}: ${count} missing`);
        }
    }
})();

return;

Which has the following output:

Missing 436 implementations:

Missing languages by game:
02_Amazing: perl, vbnet
03_Animal: pascal, perl, vbnet
04_Awari: pascal, perl, ruby, vbnet
05_Bagels: pascal, vbnet
06_Banner: pascal, perl, ruby
07_Basketball: csharp, java, pascal, perl, python, ruby, vbnet
08_Batnum: pascal, perl, ruby
09_Battle: java, pascal, perl, python, ruby, vbnet
10_Blackjack: java, pascal, perl, python, ruby, vbnet
11_Bombardment: csharp, pascal, perl, vbnet
12_Bombs_Away: csharp, pascal, perl, python, ruby, vbnet
13_Bounce: csharp, pascal, perl, ruby, vbnet
14_Bowling: csharp, pascal, perl, ruby, vbnet
15_Boxing: csharp, pascal, perl, ruby, vbnet
16_Bug: csharp, pascal, perl, python, ruby, vbnet
17_Bullfight: java, pascal, perl, python, ruby, vbnet
18_Bullseye: pascal, python, ruby, vbnet
19_Bunny: csharp, pascal, vbnet
20_Buzzword: pascal, vbnet
21_Calendar: csharp, pascal, perl, python, ruby, vbnet
22_Change: pascal, ruby, vbnet
23_Checkers: csharp, java, pascal, perl, vbnet
24_Chemist: pascal, ruby, vbnet
25_Chief: csharp, pascal, perl, python, ruby, vbnet
26_Chomp: csharp, pascal, perl, ruby, vbnet
27_Civil_War: java, pascal, perl, python, ruby, vbnet
28_Combat: pascal, perl, ruby, vbnet
29_Craps: java, pascal, perl, ruby, vbnet
30_Cube: csharp, java, pascal, perl, ruby, vbnet
31_Depth_Charge: pascal, vbnet
32_Diamond: csharp, pascal, vbnet
33_Dice: pascal, vbnet
34_Digits: csharp, pascal, perl, ruby, vbnet
35_Even_Wins: csharp, java, pascal, perl, python, ruby, vbnet
36_Flip_Flop: csharp, pascal, perl, ruby, vbnet
37_Football: csharp, java, pascal, perl, python, ruby, vbnet
38_Fur_Trader: pascal, perl, ruby, vbnet
39_Golf: java, pascal, perl, python, ruby, vbnet
40_Gomoko: csharp, pascal, perl, python, ruby, vbnet
41_Guess: csharp, pascal, ruby, vbnet
42_Gunner: csharp, pascal, perl, ruby, vbnet
43_Hammurabi: pascal, perl, ruby, vbnet
44_Hangman: pascal, perl, ruby, vbnet
45_Hello: csharp, pascal, ruby, vbnet
46_Hexapawn: java, pascal, perl, ruby, vbnet
47_Hi-Lo: pascal, ruby, vbnet
48_High_IQ: csharp, java, pascal, perl, python, ruby, vbnet
49_Hockey: csharp, java, pascal, perl, python, ruby, vbnet
50_Horserace: csharp, java, pascal, perl, ruby, vbnet
51_Hurkle: pascal, perl, vbnet
52_Kinema: csharp, pascal, ruby, vbnet
53_King: csharp, java, pascal, perl, python, ruby, vbnet
54_Letter: csharp, pascal, ruby, vbnet
55_Life: csharp, java, pascal, perl, vbnet
56_Life_for_Two: csharp, java, pascal, perl, python, ruby, vbnet
57_Literature_Quiz: pascal, ruby, vbnet
58_Love: pascal, ruby, vbnet
59_Lunar_LEM_Rocket: csharp, java, pascal, perl, ruby, vbnet
60_Mastermind: java, pascal, perl, ruby, vbnet
61_Math_Dice: ruby, vbnet
62_Mugwump: pascal, perl, ruby, vbnet
63_Name: java, pascal, ruby, vbnet
64_Nicomachus: csharp, pascal, ruby, vbnet
65_Nim: csharp, java, pascal, perl, python, ruby, vbnet
66_Number: csharp, pascal, ruby, vbnet
67_One_Check: csharp, pascal, perl, python, ruby, vbnet
68_Orbit: csharp, pascal, perl, ruby, vbnet
69_Pizza: csharp, pascal, perl, ruby, vbnet
70_Poetry: csharp, pascal, ruby, vbnet
71_Poker: csharp, java, pascal, perl, python, ruby, vbnet
72_Queen: csharp, java, pascal, perl, python, ruby, vbnet
73_Reverse: csharp, pascal, perl, ruby
74_Rock_Scissors_Paper: pascal, ruby, vbnet
75_Roulette: csharp, java, pascal, perl, python, ruby, vbnet
76_Russian_Roulette: pascal, ruby, vbnet
77_Salvo: csharp, java, pascal, perl, ruby, vbnet
78_Sine_Wave: pascal, vbnet
79_Slalom: csharp, java, pascal, perl, python, ruby, vbnet
80_Slots: csharp, pascal, perl, ruby, vbnet
81_Splat: csharp, java, pascal, perl, ruby, vbnet
82_Stars: pascal, ruby, vbnet
83_Stock_Market: java, pascal, perl, python, ruby, vbnet
84_Super_Star_Trek: java, javascript, pascal, perl, ruby, vbnet
85_Synonym: csharp, pascal, ruby, vbnet
86_Target: pascal, perl, ruby, vbnet
87_3-D_Plot: pascal, vbnet
88_3-D_Tic-Tac-Toe: csharp, java, pascal, perl, ruby, vbnet
89_Tic-Tac-Toe: csharp, pascal, perl, ruby, vbnet
90_Tower: pascal, perl, ruby, vbnet
91_Train: pascal, vbnet
92_Trap: csharp, pascal, ruby, vbnet
93_23_Matches: csharp, pascal, perl, ruby, vbnet
94_War: pascal, ruby, vbnet
95_Weekday: csharp, pascal, perl, ruby, vbnet
96_Word: pascal

By language:
perl: 64 missing
vbnet: 91 missing
pascal: 93 missing
ruby: 79 missing
csharp: 52 missing
java: 31 missing
python: 25 missing
javascript: 1 missing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants