changeset 10:3ad8456efad1

Keypad exercise
author Lewin Bormann <lbo@spheniscida.de>
date Sat, 18 Mar 2023 22:25:57 +0100
parents 8499a9b9ae47
children efa39c007546
files CMakeLists.txt dynprog.cc
diffstat 2 files changed, 91 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Mon Mar 13 23:14:42 2023 +0100
+++ b/CMakeLists.txt	Sat Mar 18 22:25:57 2023 +0100
@@ -1,10 +1,10 @@
 cmake_minimum_required(VERSION 3.26)
 project(ccplay)
 
-ADD_SUBDIRECTORY(lib)
 
 SET(CMAKE_CXX_COMPILER g++)
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -Wall")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -g -Wall")
+ADD_SUBDIRECTORY(lib)
 LINK_LIBRARIES(fmt)
 
 ADD_EXECUTABLE(time time.cc)
--- a/dynprog.cc	Mon Mar 13 23:14:42 2023 +0100
+++ b/dynprog.cc	Sat Mar 18 22:25:57 2023 +0100
@@ -3,6 +3,7 @@
 
 #include <functional>
 #include <iostream>
+#include <numeric>
 #include <ranges>
 #include <sstream>
 #include <string>
@@ -21,6 +22,14 @@
         }
 };
 
+class PairHash : function<size_t(const MemoKey &)> {
+    public:
+        template<typename T, typename U>
+            size_t operator()(const pair<T, U>& p) const {
+                return hash<T>{}(p.first) ^ hash<U>{}(p.second);
+            }
+};
+
 template <typename T>
 size_t lcss_inner(
         const vector<T> &a, const vector<T> &b, size_t i, size_t j, size_t length,
@@ -147,7 +156,7 @@
             longest, result, seqixs);
 
     vector<T> seq(longest);
-    for (int i = 0; i < seq.size(); i++)
+    for (size_t i = 0; i < seq.size(); i++)
         seq.at(i) = a.at(seqixs.at(i));
     fmt::print("Longest incr. subsequence is: {}\n", seq);
 }
@@ -171,7 +180,7 @@
             highest, result, seqixs);
 
     vector<T> seq(seqixs.size());
-    for (int i = 0; i < seq.size(); i++) {
+    for (size_t i = 0; i < seq.size(); i++) {
         if (i > 0 && seqixs.at(i) == 0)
             break;
         seq.at(i) = a.at(seqixs.at(i));
@@ -179,6 +188,83 @@
     fmt::print("Max sum incr. subsequence is: {}\n", seq);
 }
 
+template<typename T>
+string digits2string(const vector<T>& v) {
+    ostringstream s;
+    for (const T& e : v) {
+        s << e;
+    }
+    return s.str();
+}
+
+void keypad(const unordered_map<int, vector<int>>& adj, vector<int> seq, int n) {
+    if (n <= 0) {
+        cout << digits2string(seq) << " ";
+    } else {
+        if (seq.empty()) {
+            for (int k : views::keys(adj)) {
+                keypad(adj, vector<int>{k}, n-1);
+            }
+        } else {
+            int last = seq.back();
+            const vector<int>& neighbors = adj.at(last);
+            for (int neigh : neighbors ) {
+                seq.push_back(neigh);
+                keypad(adj, seq, n-1);
+                seq.pop_back();
+            }
+        }
+    }
+}
+
+size_t count_keypad(const unordered_map<int, vector<int>>& adj, int last, int n, unordered_map<pair<int,int>, size_t, PairHash>& memo) {
+    if (n == 0)
+        return 1;
+
+    /*const auto memopos = memo.find(make_pair(last, n));
+      if (memopos != memo.end())
+      return memopos->second;*/
+
+    if (last < 0) {
+        const auto ks = views::keys(adj);
+        auto tf = views::transform(ks, [&adj, &memo, n](int key) -> size_t { return count_keypad(adj, key, n-1, memo); });
+        size_t result = reduce(tf.begin(), tf.end());
+        memo.insert(make_pair(make_pair(last, n), result));
+        return result;
+    } else {
+        const auto& neighbors = adj.at(last);
+        const auto counts = views::transform(neighbors, [&adj, &memo, n](int neigh) -> size_t { return count_keypad(adj, neigh, n-1, memo); });
+        size_t result = reduce(counts.begin(), counts.end());
+        memo.insert(make_pair(make_pair(last, n), result));
+        return result;
+    }
+}
+
+// https://www.techiedelight.com/count-total-possible-combinations-n-digit-numbers-mobile-keypad/
+void evaluate_keypad(size_t n = 2) {
+    unordered_map<int, vector<int>> adjacency{
+        {1, {1, 2, 4}},
+            {2, {1, 2, 3, 5}},
+            {3, {2, 3, 6}},
+            {4, {1, 4, 5, 7}},
+            {5, {2, 5, 6, 8, 4}},
+            {6, {3, 6, 5, 9}},
+            {7, {4, 7, 8}},
+            {8, {7, 5, 8, 9, 0}},
+            {9, {6, 8, 9}},
+            {0, {0, 8}},
+    };
+    unordered_map<pair<int, int>, size_t, PairHash> memo;
+
+
+    //keypad(adjacency, vector<int>{}, n);
+    cout << endl;
+
+    size_t ck = timeit_f(function([&adjacency, &memo, n]() { return count_keypad(adjacency, -1, n, memo); }), "count_keypad");
+    fmt::print("count = {}\n", ck);
+
+}
+
 int lcss_main(void) {
 
     vector<int> a{1, 6, 2, -1, 3, 55, 2, 4, 23, 5, 6, 7, 8, 9, 10};
@@ -201,6 +287,6 @@
     vector<int> a{-1, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11};
     // Expect: 0,2,6,9,13 or ,11
     // or 0,4,6,9,13
-    evaluate_msis(a);
+    evaluate_keypad(6);
     return 0;
 }