Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Challenges

Post History

66%
+2 −0
Challenges Cod golf: condense your shoal

C++, 64 bytes gnopbristh aloumericpaendogjaw fresmudolphwartingsucker caytfish Found using another heuristic-based approach. In each iteration, we choose the string with the lowest ratio of le...

posted 6mo ago by Moshi‭  ·  edited 6mo ago by Moshi‭

Answer
#2: Post edited by user avatar Moshi‭ · 2026-03-16T03:18:33Z (6 months ago)
  • ## C++, 72 bytes
  • ```
  • spncfljorath bamverbolppiufngczaone frdeshdlowatbveryc icdatknbfisthlaeo
  • ```
  • Done using a simple heuristic-based approach.
  • We maintain a set of strings, and in each iteration attempt to find the pair of strings that has the smallest increase in length when merged into their [shortest common supersequence](https://en.wikipedia.org/wiki/Shortest_common_supersequence).
  • We repeat until we find a string with at least 255 fishes.
  • <details>
  • <summary>Code</summary>
  • ```cpp
  • #include <algorithm>
  • #include <fstream>
  • #include <map>
  • #include <mdspan>
  • #include <memory>
  • #include <print>
  • #include <set>
  • #include <string>
  • #include <string_view>
  • #include <vector>
  • void scs_table_fill(std::string_view a, std::string_view b, auto scs) {
  • auto const n = a.size();
  • auto const m = b.size();
  • for (std::size_t i = 0; i < n + 1; ++i) {
  • scs[i, 0] = i;
  • }
  • for (std::size_t j = 0; j < m + 1; ++j) {
  • scs[0, j] = j;
  • }
  • for (std::size_t i = 1; i < n + 1; ++i) {
  • for (std::size_t j = 1; j < m + 1; ++j) {
  • if (a[i - 1] == b[j - 1]) {
  • scs[i, j] = scs[i - 1, j - 1] + 1;
  • } else {
  • scs[i, j] = std::min(scs[i - 1, j], scs[i, j - 1]) + 1;
  • }
  • }
  • }
  • }
  • std::size_t scs_length(std::string_view a, std::string_view b) {
  • auto const n = a.size();
  • auto const m = b.size();
  • auto dp = std::make_unique<std::size_t[]>((n + 1) * (m + 1));
  • std::mdspan scs{dp.get(), n + 1, m + 1};
  • scs_table_fill(a, b, scs);
  • return scs[n, m];
  • }
  • std::string scs_string(std::string_view a, std::string_view b) {
  • auto const n = a.size();
  • auto const m = b.size();
  • auto dp = std::make_unique<std::size_t[]>((n + 1) * (m + 1));
  • std::mdspan scs{dp.get(), n + 1, m + 1};
  • scs_table_fill(a, b, scs);
  • std::string result;
  • std::size_t i = n;
  • std::size_t j = m;
  • while (i > 0 and j > 0) {
  • if (a[i - 1] == b[j - 1]) {
  • result.push_back(a[i - 1]);
  • i--;
  • j--;
  • } else if (scs[i - 1, j] < scs[i, j - 1]) {
  • result.push_back(a[i - 1]);
  • i--;
  • } else {
  • result.push_back(b[j - 1]);
  • j--;
  • }
  • }
  • while (i > 0) {
  • result.push_back(a[i - 1]);
  • i--;
  • }
  • while (j > 0) {
  • result.push_back(b[j - 1]);
  • j--;
  • }
  • std::ranges::reverse(result);
  • return result;
  • }
  • int main(int argc, char **argv) {
  • if (argc != 2) {
  • std::println(stderr, "Usage: {} <file>", argv[0]);
  • return 1;
  • }
  • std::vector<std::string> fishes;
  • std::ifstream ifs{argv[1]};
  • std::string buffer;
  • while (std::getline(ifs, buffer)) {
  • fishes.emplace_back(std::move(buffer));
  • }
  • std::println("Read {} fishes", fishes.size());
  • std::map<std::string, std::set<std::string_view>> strings;
  • auto const count_fishes = [&](std::string_view string,
  • std::set<std::string_view> &contains) {
  • for (std::string const &fish : fishes) {
  • if (string.size() >= fish.size() and
  • scs_length(string, fish) == string.size()) {
  • contains.emplace(fish);
  • }
  • }
  • };
  • for (std::string const &fish : fishes) {
  • std::set<std::string_view> contains;
  • count_fishes(fish, contains);
  • strings.emplace(fish, std::move(contains));
  • }
  • while (true) {
  • decltype(strings)::iterator best_a, best_b;
  • std::size_t best_delta = std::numeric_limits<std::size_t>::max();
  • auto const reset_best = [&] {
  • best_delta = std::numeric_limits<std::size_t>::max();
  • best_a = {};
  • best_b = {};
  • };
  • auto a = strings.begin();
  • outer:
  • while (a != strings.end()) {
  • auto b = strings.begin();
  • while (b != a) {
  • auto &[a_str, a_set] = *a;
  • auto &[b_str, b_set] = *b;
  • auto scs_len = scs_length(a_str, b_str);
  • // is this a good heuristic? who knows
  • auto delta = scs_len - std::max(a_str.size(), b_str.size());
  • if (delta == 0) {
  • if (a_str.size() > b_str.size()) {
  • if (best_a == b or best_b == b) {
  • reset_best();
  • }
  • std::println("'{}' -> '{}'", b_str, a_str);
  • b = strings.erase(b);
  • } else {
  • if (best_a == a or best_b == a) {
  • reset_best();
  • }
  • std::println("'{}' -> '{}'", a_str, b_str);
  • a = strings.erase(a);
  • goto outer;
  • }
  • } else if (delta < best_delta) {
  • best_a = a;
  • best_b = b;
  • best_delta = delta;
  • ++b;
  • } else {
  • ++b;
  • }
  • }
  • ++a;
  • }
  • if (best_delta == std::numeric_limits<std::size_t>::max()) {
  • continue;
  • }
  • auto &[a_str, a_set] = *best_a;
  • auto &[b_str, b_set] = *best_b;
  • auto scs = scs_string(a_str, b_str);
  • std::set<std::string_view> merged;
  • count_fishes(scs, merged);
  • if (merged.size() >= 255) {
  • std::println("{}", scs);
  • for (auto const &fish : merged) {
  • std::print("'{}' ", fish);
  • }
  • break;
  • }
  • std::println("'{}' '{}' -> '{}' ({})", a_str, b_str, scs, merged.size());
  • strings.erase(best_a);
  • strings.erase(best_b);
  • strings.emplace(std::move(scs), std::move(merged));
  • }
  • }
  • ```
  • </details>
  • ## C++, 64 bytes
  • ```
  • gnopbristh aloumericpaendogjaw fresmudolphwartingsucker caytfish
  • ```
  • Found using another heuristic-based approach.
  • In each iteration, we choose the string with the lowest ratio of length to number of contained fishes, and calculate the [shortest common supersequence](https://en.wikipedia.org/wiki/Shortest_common_supersequence) of it and every other string.
  • I left it running for a while and this was the best result, though it is possible if I ran it longer it might find something better.
  • <details>
  • <summary>Code</summary>
  • ```cpp
  • #include <algorithm>
  • #include <fstream>
  • #include <mdspan>
  • #include <print>
  • #include <ranges>
  • #include <set>
  • #include <string>
  • #include <string_view>
  • #include <vector>
  • void scs_table_fill(std::string_view a, std::string_view b,
  • std::vector<std::size_t> &buffer) {
  • auto const n = a.size();
  • auto const m = b.size();
  • buffer.reserve((n + 1) * (m + 1));
  • std::mdspan scs{buffer.data(), n + 1, m + 1};
  • for (std::size_t i = 0; i < n + 1; ++i) {
  • scs[i, 0] = i;
  • }
  • for (std::size_t j = 0; j < m + 1; ++j) {
  • scs[0, j] = j;
  • }
  • for (std::size_t i = 1; i < n + 1; ++i) {
  • for (std::size_t j = 1; j < m + 1; ++j) {
  • if (a[i - 1] == b[j - 1]) {
  • scs[i, j] = scs[i - 1, j - 1] + 1;
  • } else {
  • scs[i, j] = std::min(scs[i - 1, j], scs[i, j - 1]) + 1;
  • }
  • }
  • }
  • }
  • std::size_t scs_length(std::string_view a, std::string_view b,
  • std::size_t *buffer) {
  • auto const n = a.size();
  • auto const m = b.size();
  • std::mdspan scs{buffer, n + 1, m + 1};
  • return scs[n, m];
  • }
  • std::string scs_string(std::string_view a, std::string_view b,
  • std::size_t *buffer) {
  • auto const n = a.size();
  • auto const m = b.size();
  • std::mdspan scs{buffer, n + 1, m + 1};
  • std::string result;
  • result.reserve(scs[n, m]);
  • std::size_t i = n;
  • std::size_t j = m;
  • while (i > 0 and j > 0) {
  • if (a[i - 1] == b[j - 1]) {
  • result.push_back(a[i - 1]);
  • i--;
  • j--;
  • } else if (scs[i - 1, j] < scs[i, j - 1]) {
  • result.push_back(a[i - 1]);
  • i--;
  • } else {
  • result.push_back(b[j - 1]);
  • j--;
  • }
  • }
  • while (i > 0) {
  • result.push_back(a[i - 1]);
  • i--;
  • }
  • while (j > 0) {
  • result.push_back(b[j - 1]);
  • j--;
  • }
  • std::ranges::reverse(result);
  • return result;
  • }
  • struct scs_pair {
  • double ratio;
  • std::string string;
  • auto operator<=>(scs_pair const &other) const = default;
  • };
  • bool has_subsequence(std::string_view a, std::string_view b) {
  • char const *p = a.data();
  • char const *end = a.data() + a.size();
  • for (char c : b) {
  • while (p != end and *p != c) {
  • ++p;
  • }
  • if (p == end) {
  • return false;
  • }
  • ++p;
  • }
  • return true;
  • }
  • int main(int argc, char **argv) {
  • if (argc != 2) {
  • std::println(stderr, "Usage: {} <file>", argv[0]);
  • return 1;
  • }
  • std::vector<std::string> fishes;
  • std::ifstream ifs{argv[1]};
  • std::string line;
  • while (std::getline(ifs, line)) {
  • fishes.emplace_back(std::move(line));
  • }
  • std::println("Read {} fishes", fishes.size());
  • std::vector<std::size_t> buffer;
  • auto const count_fishes = [&](std::string_view string) {
  • return std::ranges::count_if(fishes, [&](auto const &fish) {
  • return has_subsequence(string, fish);
  • });
  • };
  • std::set<std::string> strings{std::from_range, fishes};
  • std::set<scs_pair> pairs;
  • for (auto a = strings.begin(); a != strings.end(); ++a) {
  • for (auto b = strings.begin(); b != a; ++b) {
  • auto &a_str = *a;
  • auto &b_str = *b;
  • scs_table_fill(a_str, b_str, buffer);
  • auto scs = scs_string(a_str, b_str, buffer.data());
  • if (strings.contains(scs)) {
  • continue;
  • }
  • auto count = count_fishes(scs);
  • double ratio = static_cast<double>(scs.size()) / count;
  • pairs.emplace(ratio, scs);
  • }
  • }
  • std::string current_solution;
  • while (true) {
  • auto iter = pairs.begin();
  • auto count = count_fishes(iter->string);
  • if (count >= 255) {
  • if (iter->string.size() < current_solution.size() ||
  • current_solution.empty()) {
  • std::println("Possible solution: {} ({}, {}, {})", iter->string, iter->string.size(), count, iter->ratio);
  • current_solution = iter->string;
  • }
  • } else {
  • for (auto &a_str : strings) {
  • scs_table_fill(a_str, iter->string, buffer);
  • auto scs = scs_string(a_str, iter->string, buffer.data());
  • if (strings.contains(scs)) {
  • continue;
  • }
  • auto count = count_fishes(scs);
  • double ratio = static_cast<double>(scs.size()) / count;
  • pairs.emplace(ratio, scs);
  • }
  • strings.emplace(iter->string);
  • }
  • pairs.erase(iter);
  • }
  • }
  • ```
  • </details>
  • ## C++, 72 bytes
  • ```
  • spncfljorath bamverbolppiufngczaone frdeshdlowatbveryc icdatknbfisthlaeo
  • ```
  • Done using a simple heuristic-based approach.
  • We maintain a set of strings, and in each iteration attempt to find the pair of strings that has the smallest increase in length when merged into their [shortest common supersequence](https://en.wikipedia.org/wiki/Shortest_common_supersequence).
  • We repeat until we find a string with at least 255 fishes.
  • <details>
  • <summary>Code</summary>
  • ```cpp
  • #include <algorithm>
  • #include <fstream>
  • #include <map>
  • #include <mdspan>
  • #include <memory>
  • #include <print>
  • #include <set>
  • #include <string>
  • #include <string_view>
  • #include <vector>
  • void scs_table_fill(std::string_view a, std::string_view b, auto scs) {
  • auto const n = a.size();
  • auto const m = b.size();
  • for (std::size_t i = 0; i < n + 1; ++i) {
  • scs[i, 0] = i;
  • }
  • for (std::size_t j = 0; j < m + 1; ++j) {
  • scs[0, j] = j;
  • }
  • for (std::size_t i = 1; i < n + 1; ++i) {
  • for (std::size_t j = 1; j < m + 1; ++j) {
  • if (a[i - 1] == b[j - 1]) {
  • scs[i, j] = scs[i - 1, j - 1] + 1;
  • } else {
  • scs[i, j] = std::min(scs[i - 1, j], scs[i, j - 1]) + 1;
  • }
  • }
  • }
  • }
  • std::size_t scs_length(std::string_view a, std::string_view b) {
  • auto const n = a.size();
  • auto const m = b.size();
  • auto dp = std::make_unique<std::size_t[]>((n + 1) * (m + 1));
  • std::mdspan scs{dp.get(), n + 1, m + 1};
  • scs_table_fill(a, b, scs);
  • return scs[n, m];
  • }
  • std::string scs_string(std::string_view a, std::string_view b) {
  • auto const n = a.size();
  • auto const m = b.size();
  • auto dp = std::make_unique<std::size_t[]>((n + 1) * (m + 1));
  • std::mdspan scs{dp.get(), n + 1, m + 1};
  • scs_table_fill(a, b, scs);
  • std::string result;
  • std::size_t i = n;
  • std::size_t j = m;
  • while (i > 0 and j > 0) {
  • if (a[i - 1] == b[j - 1]) {
  • result.push_back(a[i - 1]);
  • i--;
  • j--;
  • } else if (scs[i - 1, j] < scs[i, j - 1]) {
  • result.push_back(a[i - 1]);
  • i--;
  • } else {
  • result.push_back(b[j - 1]);
  • j--;
  • }
  • }
  • while (i > 0) {
  • result.push_back(a[i - 1]);
  • i--;
  • }
  • while (j > 0) {
  • result.push_back(b[j - 1]);
  • j--;
  • }
  • std::ranges::reverse(result);
  • return result;
  • }
  • int main(int argc, char **argv) {
  • if (argc != 2) {
  • std::println(stderr, "Usage: {} <file>", argv[0]);
  • return 1;
  • }
  • std::vector<std::string> fishes;
  • std::ifstream ifs{argv[1]};
  • std::string buffer;
  • while (std::getline(ifs, buffer)) {
  • fishes.emplace_back(std::move(buffer));
  • }
  • std::println("Read {} fishes", fishes.size());
  • std::map<std::string, std::set<std::string_view>> strings;
  • auto const count_fishes = [&](std::string_view string,
  • std::set<std::string_view> &contains) {
  • for (std::string const &fish : fishes) {
  • if (string.size() >= fish.size() and
  • scs_length(string, fish) == string.size()) {
  • contains.emplace(fish);
  • }
  • }
  • };
  • for (std::string const &fish : fishes) {
  • std::set<std::string_view> contains;
  • count_fishes(fish, contains);
  • strings.emplace(fish, std::move(contains));
  • }
  • while (true) {
  • decltype(strings)::iterator best_a, best_b;
  • std::size_t best_delta = std::numeric_limits<std::size_t>::max();
  • auto const reset_best = [&] {
  • best_delta = std::numeric_limits<std::size_t>::max();
  • best_a = {};
  • best_b = {};
  • };
  • auto a = strings.begin();
  • outer:
  • while (a != strings.end()) {
  • auto b = strings.begin();
  • while (b != a) {
  • auto &[a_str, a_set] = *a;
  • auto &[b_str, b_set] = *b;
  • auto scs_len = scs_length(a_str, b_str);
  • // is this a good heuristic? who knows
  • auto delta = scs_len - std::max(a_str.size(), b_str.size());
  • if (delta == 0) {
  • if (a_str.size() > b_str.size()) {
  • if (best_a == b or best_b == b) {
  • reset_best();
  • }
  • std::println("'{}' -> '{}'", b_str, a_str);
  • b = strings.erase(b);
  • } else {
  • if (best_a == a or best_b == a) {
  • reset_best();
  • }
  • std::println("'{}' -> '{}'", a_str, b_str);
  • a = strings.erase(a);
  • goto outer;
  • }
  • } else if (delta < best_delta) {
  • best_a = a;
  • best_b = b;
  • best_delta = delta;
  • ++b;
  • } else {
  • ++b;
  • }
  • }
  • ++a;
  • }
  • if (best_delta == std::numeric_limits<std::size_t>::max()) {
  • continue;
  • }
  • auto &[a_str, a_set] = *best_a;
  • auto &[b_str, b_set] = *best_b;
  • auto scs = scs_string(a_str, b_str);
  • std::set<std::string_view> merged;
  • count_fishes(scs, merged);
  • if (merged.size() >= 255) {
  • std::println("{}", scs);
  • for (auto const &fish : merged) {
  • std::print("'{}' ", fish);
  • }
  • break;
  • }
  • std::println("'{}' '{}' -> '{}' ({})", a_str, b_str, scs, merged.size());
  • strings.erase(best_a);
  • strings.erase(best_b);
  • strings.emplace(std::move(scs), std::move(merged));
  • }
  • }
  • ```
  • </details>
#1: Initial revision by user avatar Moshi‭ · 2026-03-15T10:59:27Z (6 months ago)
## C++, 72 bytes

```
spncfljorath bamverbolppiufngczaone frdeshdlowatbveryc icdatknbfisthlaeo
```

Done using a simple heuristic-based approach.
We maintain a set of strings, and in each iteration attempt to find the pair of strings that has the smallest increase in length when merged into their [shortest common supersequence](https://en.wikipedia.org/wiki/Shortest_common_supersequence).

We repeat until we find a string with at least 255 fishes.

<details>
<summary>Code</summary>

```cpp
#include <algorithm>
#include <fstream>
#include <map>
#include <mdspan>
#include <memory>
#include <print>
#include <set>
#include <string>
#include <string_view>
#include <vector>

void scs_table_fill(std::string_view a, std::string_view b, auto scs) {
  auto const n = a.size();
  auto const m = b.size();
  for (std::size_t i = 0; i < n + 1; ++i) {
    scs[i, 0] = i;
  }
  for (std::size_t j = 0; j < m + 1; ++j) {
    scs[0, j] = j;
  }

  for (std::size_t i = 1; i < n + 1; ++i) {
    for (std::size_t j = 1; j < m + 1; ++j) {
      if (a[i - 1] == b[j - 1]) {
        scs[i, j] = scs[i - 1, j - 1] + 1;
      } else {
        scs[i, j] = std::min(scs[i - 1, j], scs[i, j - 1]) + 1;
      }
    }
  }
}

std::size_t scs_length(std::string_view a, std::string_view b) {
  auto const n = a.size();
  auto const m = b.size();
  auto dp = std::make_unique<std::size_t[]>((n + 1) * (m + 1));

  std::mdspan scs{dp.get(), n + 1, m + 1};
  scs_table_fill(a, b, scs);
  return scs[n, m];
}

std::string scs_string(std::string_view a, std::string_view b) {
  auto const n = a.size();
  auto const m = b.size();
  auto dp = std::make_unique<std::size_t[]>((n + 1) * (m + 1));

  std::mdspan scs{dp.get(), n + 1, m + 1};
  scs_table_fill(a, b, scs);

  std::string result;

  std::size_t i = n;
  std::size_t j = m;

  while (i > 0 and j > 0) {
    if (a[i - 1] == b[j - 1]) {
      result.push_back(a[i - 1]);
      i--;
      j--;
    } else if (scs[i - 1, j] < scs[i, j - 1]) {
      result.push_back(a[i - 1]);
      i--;
    } else {
      result.push_back(b[j - 1]);
      j--;
    }
  }

  while (i > 0) {
    result.push_back(a[i - 1]);
    i--;
  }
  while (j > 0) {
    result.push_back(b[j - 1]);
    j--;
  }

  std::ranges::reverse(result);

  return result;
}

int main(int argc, char **argv) {
  if (argc != 2) {
    std::println(stderr, "Usage: {} <file>", argv[0]);
    return 1;
  }

  std::vector<std::string> fishes;
  std::ifstream ifs{argv[1]};

  std::string buffer;
  while (std::getline(ifs, buffer)) {
    fishes.emplace_back(std::move(buffer));
  }

  std::println("Read {} fishes", fishes.size());

  std::map<std::string, std::set<std::string_view>> strings;

  auto const count_fishes = [&](std::string_view string,
                                std::set<std::string_view> &contains) {
    for (std::string const &fish : fishes) {
      if (string.size() >= fish.size() and
          scs_length(string, fish) == string.size()) {
        contains.emplace(fish);
      }
    }
  };

  for (std::string const &fish : fishes) {
    std::set<std::string_view> contains;
    count_fishes(fish, contains);
    strings.emplace(fish, std::move(contains));
  }

  while (true) {
    decltype(strings)::iterator best_a, best_b;
    std::size_t best_delta = std::numeric_limits<std::size_t>::max();

    auto const reset_best = [&] {
      best_delta = std::numeric_limits<std::size_t>::max();
      best_a = {};
      best_b = {};
    };

    auto a = strings.begin();
  outer:
    while (a != strings.end()) {
      auto b = strings.begin();
      while (b != a) {
        auto &[a_str, a_set] = *a;
        auto &[b_str, b_set] = *b;
        auto scs_len = scs_length(a_str, b_str);
        // is this a good heuristic? who knows
        auto delta = scs_len - std::max(a_str.size(), b_str.size());
        if (delta == 0) {
          if (a_str.size() > b_str.size()) {
            if (best_a == b or best_b == b) {
              reset_best();
            }
            std::println("'{}' -> '{}'", b_str, a_str);
            b = strings.erase(b);
          } else {
            if (best_a == a or best_b == a) {
              reset_best();
            }
            std::println("'{}' -> '{}'", a_str, b_str);
            a = strings.erase(a);
            goto outer;
          }
        } else if (delta < best_delta) {
          best_a = a;
          best_b = b;
          best_delta = delta;
          ++b;
        } else {
          ++b;
        }
      }
      ++a;
    }

    if (best_delta == std::numeric_limits<std::size_t>::max()) {
      continue;
    }

    auto &[a_str, a_set] = *best_a;
    auto &[b_str, b_set] = *best_b;

    auto scs = scs_string(a_str, b_str);
    std::set<std::string_view> merged;
    count_fishes(scs, merged);
    if (merged.size() >= 255) {
      std::println("{}", scs);
      for (auto const &fish : merged) {
        std::print("'{}' ", fish);
      }
      break;
    }

    std::println("'{}' '{}' -> '{}' ({})", a_str, b_str, scs, merged.size());
    strings.erase(best_a);
    strings.erase(best_b);
    strings.emplace(std::move(scs), std::move(merged));
  }
}
```

</details>