diff options
author | Star Rauchenberger <fefferburbia@gmail.com> | 2022-12-10 16:45:29 -0500 |
---|---|---|
committer | Star Rauchenberger <fefferburbia@gmail.com> | 2022-12-10 16:45:29 -0500 |
commit | 807b1f049bcc4597400eea21228875efe098ebc5 (patch) | |
tree | 1e7a87187a616f0488822b1750c1b30b7e84a97d | |
parent | dad0c0c6dc5a6c04f305f71ed78ca99f85cca78c (diff) | |
download | lingo-807b1f049bcc4597400eea21228875efe098ebc5.tar.gz lingo-807b1f049bcc4597400eea21228875efe098ebc5.tar.bz2 lingo-807b1f049bcc4597400eea21228875efe098ebc5.zip |
Added orange puzzles
fixes #23
-rw-r--r-- | generate_orange.rb | 56 | ||||
-rw-r--r-- | lingo.cpp | 70 |
2 files changed, 119 insertions, 7 deletions
diff --git a/generate_orange.rb b/generate_orange.rb new file mode 100644 index 0000000..310f823 --- /dev/null +++ b/generate_orange.rb | |||
@@ -0,0 +1,56 @@ | |||
1 | require 'sqlite3' | ||
2 | |||
3 | db = SQLite3::Database.open ARGV[0] | ||
4 | form_rows = db.query "SELECT form FROM forms WHERE proper = 0" | ||
5 | |||
6 | wanderlust = {} | ||
7 | wanderlust["w"] = "1" | ||
8 | wanderlust["a"] = "2" | ||
9 | wanderlust["n"] = "3" | ||
10 | wanderlust["d"] = "4" | ||
11 | wanderlust["e"] = "5" | ||
12 | wanderlust["r"] = "6" | ||
13 | wanderlust["l"] = "7" | ||
14 | wanderlust["u"] = "8" | ||
15 | wanderlust["s"] = "9" | ||
16 | wanderlust["t"] = "0" | ||
17 | |||
18 | forms = form_rows.map {|row| row[0].downcase} | ||
19 | orange_forms = forms.reject {|form| /^[wanderlust]*$/.match(form).nil?}.select {|form| form.length >= 3} | ||
20 | words = orange_forms.map do |form| | ||
21 | oranged = form.chars.map {|letter| wanderlust[letter]}.join | ||
22 | [form, oranged, oranged.to_i] | ||
23 | end | ||
24 | words.sort_by! {|word| word[2]} | ||
25 | |||
26 | puts words.length | ||
27 | puts words[10] | ||
28 | puts words.sample | ||
29 | puts "" | ||
30 | |||
31 | oranges_by_num = {} | ||
32 | puzzles = [] | ||
33 | words.each do |vals| | ||
34 | oranges_by_num.each do |num, form| | ||
35 | opposite = (vals[2] - num.to_i).to_s | ||
36 | if oranges_by_num.include? opposite | ||
37 | puzzles << ["#{form} + #{oranges_by_num[opposite]}", vals[0]] | ||
38 | puzzles << ["#{oranges_by_num[opposite]} + #{form}", vals[0]] | ||
39 | end | ||
40 | opposite = "0" + opposite | ||
41 | if oranges_by_num.include? opposite | ||
42 | puzzles << ["#{form} + #{oranges_by_num[opposite]}", vals[0]] | ||
43 | puzzles << ["#{oranges_by_num[opposite]} + #{form}", vals[0]] | ||
44 | end | ||
45 | end | ||
46 | oranges_by_num[vals[1]] = vals[0] | ||
47 | end | ||
48 | |||
49 | puts puzzles.length | ||
50 | puts puzzles.sample | ||
51 | |||
52 | File.open("wanderlust.txt", "w") do |f| | ||
53 | puzzles.each do |puzzle| | ||
54 | f.write("#{puzzle[0]}\n#{puzzle[1]}\n") | ||
55 | end | ||
56 | end | ||
diff --git a/lingo.cpp b/lingo.cpp index c2f36af..12471d1 100644 --- a/lingo.cpp +++ b/lingo.cpp | |||
@@ -37,6 +37,7 @@ enum Colour { | |||
37 | kBrown, | 37 | kBrown, |
38 | kYellow, | 38 | kYellow, |
39 | kGreen, | 39 | kGreen, |
40 | kOrange, | ||
40 | kColourCount | 41 | kColourCount |
41 | }; | 42 | }; |
42 | 43 | ||
@@ -48,7 +49,8 @@ const std::string COLOUR_EMOJIS[kColourCount] = { | |||
48 | "🟪", | 49 | "🟪", |
49 | "🟫", | 50 | "🟫", |
50 | "🟨", | 51 | "🟨", |
51 | "🟩" | 52 | "🟩", |
53 | "🟧", | ||
52 | }; | 54 | }; |
53 | 55 | ||
54 | const std::string NONE_EMOTE = "<:xx:1047267830535557180>"; | 56 | const std::string NONE_EMOTE = "<:xx:1047267830535557180>"; |
@@ -61,7 +63,8 @@ const std::string COLOUR_EMOTES[kColourCount] = { | |||
61 | "<:pr:1047262146926489691>", | 63 | "<:pr:1047262146926489691>", |
62 | "<:bn:1047262139187998790>", | 64 | "<:bn:1047262139187998790>", |
63 | "<:yw:1047262152781737986>", | 65 | "<:yw:1047262152781737986>", |
64 | "<:gn:1047262141914304633>" | 66 | "<:gn:1047262141914304633>", |
67 | "<:or:1047262144934182983>", | ||
65 | }; | 68 | }; |
66 | 69 | ||
67 | enum FilterDirection { | 70 | enum FilterDirection { |
@@ -272,6 +275,33 @@ verbly::filter makeHintFilter(verbly::filter subfilter, Height height, Colour co | |||
272 | return {}; | 275 | return {}; |
273 | } | 276 | } |
274 | 277 | ||
278 | class wanderlust { | ||
279 | public: | ||
280 | explicit wanderlust(const std::string& filename) | ||
281 | { | ||
282 | std::ifstream file(filename); | ||
283 | std::string line; | ||
284 | while (std::getline(file, line)) | ||
285 | { | ||
286 | std::string line2; | ||
287 | if (!std::getline(file, line2)) | ||
288 | { | ||
289 | throw std::invalid_argument("Wanderlust file is malformed."); | ||
290 | } | ||
291 | |||
292 | puzzles_.emplace_back(line, line2); | ||
293 | } | ||
294 | } | ||
295 | |||
296 | std::tuple<std::string, std::string> getPuzzle(std::mt19937& rng) const | ||
297 | { | ||
298 | return puzzles_.at(std::uniform_int_distribution<int>(0, puzzles_.size()-1)(rng)); | ||
299 | } | ||
300 | |||
301 | private: | ||
302 | std::vector<std::tuple<std::string, std::string>> puzzles_; | ||
303 | }; | ||
304 | |||
275 | class lingo { | 305 | class lingo { |
276 | public: | 306 | public: |
277 | lingo(std::mt19937& rng) : rng_(rng) {} | 307 | lingo(std::mt19937& rng) : rng_(rng) {} |
@@ -380,6 +410,7 @@ public: | |||
380 | 410 | ||
381 | database_ = std::make_unique<verbly::database>(config["verbly_datafile"].as<std::string>()); | 411 | database_ = std::make_unique<verbly::database>(config["verbly_datafile"].as<std::string>()); |
382 | imagenet_ = std::make_unique<imagenet>(config["imagenet"].as<std::string>()); | 412 | imagenet_ = std::make_unique<imagenet>(config["imagenet"].as<std::string>()); |
413 | wanderlust_ = std::make_unique<wanderlust>(config["wanderlust"].as<std::string>()); | ||
383 | 414 | ||
384 | scoreboard_endpoint_ = config["scoreboard_endpoint"].as<std::string>(); | 415 | scoreboard_endpoint_ = config["scoreboard_endpoint"].as<std::string>(); |
385 | scoreboard_secret_code_ = config["scoreboard_secret_code"].as<std::string>(); | 416 | scoreboard_secret_code_ = config["scoreboard_secret_code"].as<std::string>(); |
@@ -407,6 +438,7 @@ private: | |||
407 | {kMiddle, kBlue}, | 438 | {kMiddle, kBlue}, |
408 | {kMiddle, kPurple}, | 439 | {kMiddle, kPurple}, |
409 | {kMiddle, kGreen}, | 440 | {kMiddle, kGreen}, |
441 | {kMiddle, kOrange}, | ||
410 | {kBottom, kWhite}, | 442 | {kBottom, kWhite}, |
411 | {kBottom, kBlack}, | 443 | {kBottom, kBlack}, |
412 | {kBottom, kRed}, | 444 | {kBottom, kRed}, |
@@ -447,6 +479,7 @@ private: | |||
447 | int expensive_uses = 0; | 479 | int expensive_uses = 0; |
448 | int moderate_uses = 0; | 480 | int moderate_uses = 0; |
449 | int green_uses = 0; | 481 | int green_uses = 0; |
482 | int orange_uses = 0; | ||
450 | std::array<std::optional<Colour>, kHeightCount> parts; | 483 | std::array<std::optional<Colour>, kHeightCount> parts; |
451 | for (int height = 0; height < static_cast<int>(kHeightCount); height++) { | 484 | for (int height = 0; height < static_cast<int>(kHeightCount); height++) { |
452 | if (std::bernoulli_distribution(0.5)(rng_)) { | 485 | if (std::bernoulli_distribution(0.5)(rng_)) { |
@@ -472,6 +505,10 @@ private: | |||
472 | { | 505 | { |
473 | green_uses++; | 506 | green_uses++; |
474 | } | 507 | } |
508 | if (colour == kOrange) | ||
509 | { | ||
510 | orange_uses++; | ||
511 | } | ||
475 | 512 | ||
476 | std::cout << COLOUR_EMOJIS[colour]; | 513 | std::cout << COLOUR_EMOJIS[colour]; |
477 | } else { | 514 | } else { |
@@ -503,6 +540,13 @@ private: | |||
503 | continue; | 540 | continue; |
504 | } | 541 | } |
505 | 542 | ||
543 | std::string orange_clue; | ||
544 | std::string orange_solution; | ||
545 | if (orange_uses > 0) | ||
546 | { | ||
547 | std::tie(orange_clue, orange_solution) = wanderlust_->getPuzzle(rng_); | ||
548 | } | ||
549 | |||
506 | verbly::filter forwardFilter = cleanFilter && wordFilter; | 550 | verbly::filter forwardFilter = cleanFilter && wordFilter; |
507 | for (int i=0; i<static_cast<int>(kHeightCount); i++) { | 551 | for (int i=0; i<static_cast<int>(kHeightCount); i++) { |
508 | Height height = static_cast<Height>(i); | 552 | Height height = static_cast<Height>(i); |
@@ -510,7 +554,12 @@ private: | |||
510 | if (!colour.has_value()) { | 554 | if (!colour.has_value()) { |
511 | continue; | 555 | continue; |
512 | } | 556 | } |
513 | forwardFilter &= makeHintFilter(wordFilter, height, *colour, kTowardSolution); | 557 | if (*colour == kOrange) |
558 | { | ||
559 | forwardFilter &= (verbly::form::text == orange_solution); | ||
560 | } else { | ||
561 | forwardFilter &= makeHintFilter(wordFilter, height, *colour, kTowardSolution); | ||
562 | } | ||
514 | } | 563 | } |
515 | 564 | ||
516 | verbly::form solution = database_->forms(forwardFilter).first(); | 565 | verbly::form solution = database_->forms(forwardFilter).first(); |
@@ -523,11 +572,17 @@ private: | |||
523 | Height height = static_cast<Height>(i); | 572 | Height height = static_cast<Height>(i); |
524 | std::optional<Colour>& colour = parts[i]; | 573 | std::optional<Colour>& colour = parts[i]; |
525 | if (colour.has_value()) { | 574 | if (colour.has_value()) { |
526 | verbly::filter questionFilter = makeHintFilter(solution, height, *colour, kTowardQuestion); | 575 | if (*colour == kOrange) |
527 | verbly::form questionPart = database_->forms(questionFilter && cleanFilter && wordFilter).first(); | 576 | { |
528 | msg_stream << COLOUR_EMOTES[*colour] << " " << questionPart.getText() << std::endl; | 577 | msg_stream << COLOUR_EMOTES[*colour] << " " << orange_clue << std::endl; |
578 | admissible &= (verbly::form::text == orange_solution); | ||
579 | } else { | ||
580 | verbly::filter questionFilter = makeHintFilter(solution, height, *colour, kTowardQuestion); | ||
581 | verbly::form questionPart = database_->forms(questionFilter && cleanFilter && wordFilter).first(); | ||
582 | msg_stream << COLOUR_EMOTES[*colour] << " " << questionPart.getText() << std::endl; | ||
529 | 583 | ||
530 | admissible &= makeHintFilter(questionPart, height, *colour, kTowardSolution); | 584 | admissible &= makeHintFilter(questionPart, height, *colour, kTowardSolution); |
585 | } | ||
531 | } else { | 586 | } else { |
532 | msg_stream << NONE_EMOTE << std::endl; | 587 | msg_stream << NONE_EMOTE << std::endl; |
533 | } | 588 | } |
@@ -596,6 +651,7 @@ private: | |||
596 | std::mutex answers_mutex_; | 651 | std::mutex answers_mutex_; |
597 | std::string scoreboard_endpoint_; | 652 | std::string scoreboard_endpoint_; |
598 | std::string scoreboard_secret_code_; | 653 | std::string scoreboard_secret_code_; |
654 | std::unique_ptr<wanderlust> wanderlust_; | ||
599 | }; | 655 | }; |
600 | 656 | ||
601 | int main(int argc, char** argv) | 657 | int main(int argc, char** argv) |