anagrams.tlv: now fully responsive
If we press a key the computation now restarts instantly. There's no fiction of multi-threading in Teliva. If the application doesn't work right, it beach-balls. If it doesn't beach-ball under normal circumstances you're more certain it'll never beach-ball. It's more work up-front, but there's less variability in outcomes.
This commit is contained in:
parent
43dd1f382e
commit
2d6b88204b
128
anagrams.tlv
128
anagrams.tlv
|
@ -179,8 +179,8 @@
|
||||||
>end
|
>end
|
||||||
- __teliva_timestamp:
|
- __teliva_timestamp:
|
||||||
>Mon Feb 21 17:45:04 2022
|
>Mon Feb 21 17:45:04 2022
|
||||||
sort_string:
|
sort_letters:
|
||||||
>function sort_string(s)
|
>function sort_letters(s)
|
||||||
> tmp = {}
|
> tmp = {}
|
||||||
> for i=1,#s do
|
> for i=1,#s do
|
||||||
> table.insert(tmp, s[i])
|
> table.insert(tmp, s[i])
|
||||||
|
@ -193,10 +193,24 @@
|
||||||
> return result
|
> return result
|
||||||
>end
|
>end
|
||||||
>
|
>
|
||||||
>function test_sort_string(s)
|
>function test_sort_letters(s)
|
||||||
> check_eq(sort_string(''), '', 'test_sort_string: empty')
|
> check_eq(sort_letters(''), '', 'test_sort_letters: empty')
|
||||||
> check_eq(sort_string('ba'), 'ab', 'test_sort_string: non-empty')
|
> check_eq(sort_letters('ba'), 'ab', 'test_sort_letters: non-empty')
|
||||||
> check_eq(sort_string('abba'), 'aabb', 'test_sort_string: duplicates')
|
> check_eq(sort_letters('abba'), 'aabb', 'test_sort_letters: duplicates')
|
||||||
|
>end
|
||||||
|
- __teliva_timestamp: original
|
||||||
|
count_letters:
|
||||||
|
>function count_letters(s)
|
||||||
|
> local result = {}
|
||||||
|
> for i=1,string.len(s) do
|
||||||
|
> local c = s[i]
|
||||||
|
> if result[c] == nil then
|
||||||
|
> result[c] = 1
|
||||||
|
> else
|
||||||
|
> result[c] = result[c] + 1
|
||||||
|
> end
|
||||||
|
> end
|
||||||
|
> return result
|
||||||
>end
|
>end
|
||||||
- __teliva_timestamp: original
|
- __teliva_timestamp: original
|
||||||
append:
|
append:
|
||||||
|
@ -282,11 +296,6 @@
|
||||||
> for i, w in ipairs(results) do
|
> for i, w in ipairs(results) do
|
||||||
> window:addstr(w)
|
> window:addstr(w)
|
||||||
> window:addstr(' ')
|
> window:addstr(' ')
|
||||||
> local tmp = window:getch()
|
|
||||||
> if tmp then
|
|
||||||
> window:ungetch(tmp)
|
|
||||||
> break
|
|
||||||
> end
|
|
||||||
> end
|
> end
|
||||||
> end
|
> end
|
||||||
>
|
>
|
||||||
|
@ -297,7 +306,7 @@
|
||||||
>Mon Feb 21 17:42:28 2022
|
>Mon Feb 21 17:42:28 2022
|
||||||
anagrams:
|
anagrams:
|
||||||
>function anagrams(word)
|
>function anagrams(word)
|
||||||
> return gather(sort_string(word))
|
> return gather(sort_letters(word))
|
||||||
>end
|
>end
|
||||||
- __teliva_timestamp:
|
- __teliva_timestamp:
|
||||||
>Mon Feb 21 18:18:07 2022
|
>Mon Feb 21 18:18:07 2022
|
||||||
|
@ -307,7 +316,6 @@
|
||||||
> local result = {}
|
> local result = {}
|
||||||
> for i=1, #s do
|
> for i=1, #s do
|
||||||
> if i == 1 or s[i] ~= s[i-1] then
|
> if i == 1 or s[i] ~= s[i-1] then
|
||||||
> local foo = combine(s[i], gather(take_out(s, i)))
|
|
||||||
> append(result, combine(s[i], gather(take_out(s, i))))
|
> append(result, combine(s[i], gather(take_out(s, i))))
|
||||||
> end
|
> end
|
||||||
> end
|
> end
|
||||||
|
@ -330,6 +338,8 @@
|
||||||
> check_eq(take_out('abc', 2), 'ac', 'take_out: middle index')
|
> check_eq(take_out('abc', 2), 'ac', 'take_out: middle index')
|
||||||
>end
|
>end
|
||||||
- __teliva_timestamp: original
|
- __teliva_timestamp: original
|
||||||
|
__teliva_note:
|
||||||
|
>basic version
|
||||||
combine:
|
combine:
|
||||||
>-- return 'l' with each element prefixed with 'prefix'
|
>-- return 'l' with each element prefixed with 'prefix'
|
||||||
>function combine(prefix, l)
|
>function combine(prefix, l)
|
||||||
|
@ -344,3 +354,95 @@
|
||||||
>function test_combine()
|
>function test_combine()
|
||||||
> check_eq(combine('abc', {}), {'abc'}, 'test_combine: empty list')
|
> check_eq(combine('abc', {}), {'abc'}, 'test_combine: empty list')
|
||||||
>end
|
>end
|
||||||
|
- __teliva_timestamp:
|
||||||
|
>Sat Mar 5 15:24:00 2022
|
||||||
|
count_anagrams:
|
||||||
|
>function count_anagrams(s)
|
||||||
|
> local result = factorial(string.len(s))
|
||||||
|
> local letter_counts = count_letters(s)
|
||||||
|
> for k, v in pairs(letter_counts) do
|
||||||
|
> result = result / factorial(v)
|
||||||
|
> end
|
||||||
|
> return result
|
||||||
|
>end
|
||||||
|
- __teliva_timestamp:
|
||||||
|
>Sat Mar 5 15:24:34 2022
|
||||||
|
factorial:
|
||||||
|
>function factorial(n)
|
||||||
|
> local result = 1
|
||||||
|
> for i=1,n do
|
||||||
|
> result = result*i
|
||||||
|
> end
|
||||||
|
> return result
|
||||||
|
>end
|
||||||
|
- __teliva_timestamp:
|
||||||
|
>Sat Mar 5 15:53:23 2022
|
||||||
|
key_pressed:
|
||||||
|
>-- only works when nodelay (non-blocking keyboard)
|
||||||
|
>function key_pressed(window)
|
||||||
|
> local c = window:getch()
|
||||||
|
> if c == nil then return false end
|
||||||
|
> window:ungetch(c)
|
||||||
|
> return true
|
||||||
|
>end
|
||||||
|
- __teliva_timestamp:
|
||||||
|
>Sat Mar 5 15:55:34 2022
|
||||||
|
render:
|
||||||
|
>function render(window)
|
||||||
|
> window:clear()
|
||||||
|
>
|
||||||
|
> local prompt_str = ' what is your name? '
|
||||||
|
> window:attron(curses.A_REVERSE)
|
||||||
|
> window:mvaddstr(0, 0, prompt_str)
|
||||||
|
> window:attroff(curses.A_REVERSE)
|
||||||
|
> window:addstr(' ')
|
||||||
|
> window:attron(curses.A_BOLD)
|
||||||
|
> window:addstr(word)
|
||||||
|
> window:attroff(curses.A_BOLD)
|
||||||
|
> window:mvaddstr(2, 0, '')
|
||||||
|
> if #word > 0 then
|
||||||
|
> local num_anagrams = count_anagrams(word)
|
||||||
|
> window:attron(curses.A_REVERSE)
|
||||||
|
> print(num_anagrams..' anagrams')
|
||||||
|
> window:attroff(curses.A_REVERSE)
|
||||||
|
> local results = anagrams(word)
|
||||||
|
> if results == nil then -- interrupted
|
||||||
|
> window:addstr('...')
|
||||||
|
> else
|
||||||
|
> assert(#results == num_anagrams, "something's wrong; the count is unexpected")
|
||||||
|
> for i, w in ipairs(results) do
|
||||||
|
> window:addstr(w)
|
||||||
|
> window:addstr(' ')
|
||||||
|
> if key_pressed(window) then
|
||||||
|
> break
|
||||||
|
> end
|
||||||
|
> end
|
||||||
|
> end
|
||||||
|
> end
|
||||||
|
>
|
||||||
|
> window:mvaddstr(0, string.len(prompt_str)+cursor, '')
|
||||||
|
> window:refresh()
|
||||||
|
>end
|
||||||
|
- __teliva_timestamp:
|
||||||
|
>Sat Mar 5 15:56:35 2022
|
||||||
|
__teliva_note:
|
||||||
|
>restart computation when a key is pressed
|
||||||
|
gather:
|
||||||
|
>-- return a list of unique permutations of a sorted string 's'
|
||||||
|
>-- the letters in 's' must be in alphabetical order, so that duplicates are adjacent
|
||||||
|
>-- this function can take a long time for long strings, so we make it interruptible
|
||||||
|
>-- if a key is pressed, it returns nil
|
||||||
|
>-- since it's recursive, we also need to handle recursive calls returning nil
|
||||||
|
>function gather(s)
|
||||||
|
> if s == '' then return {} end
|
||||||
|
> local result = {}
|
||||||
|
> for i=1, #s do
|
||||||
|
> if i == 1 or s[i] ~= s[i-1] then
|
||||||
|
> local subresult = gather(take_out(s, i))
|
||||||
|
> if subresult == nil then return nil end -- interrupted
|
||||||
|
> append(result, combine(s[i], subresult))
|
||||||
|
> end
|
||||||
|
> if key_pressed(Window) then return nil end -- interrupted
|
||||||
|
> end
|
||||||
|
> return result
|
||||||
|
>end
|
||||||
|
|
26
template.tlv
26
template.tlv
|
@ -179,8 +179,8 @@
|
||||||
>end
|
>end
|
||||||
- __teliva_timestamp:
|
- __teliva_timestamp:
|
||||||
>Mon Feb 21 17:45:04 2022
|
>Mon Feb 21 17:45:04 2022
|
||||||
sort_string:
|
sort_letters:
|
||||||
>function sort_string(s)
|
>function sort_letters(s)
|
||||||
> tmp = {}
|
> tmp = {}
|
||||||
> for i=1,#s do
|
> for i=1,#s do
|
||||||
> table.insert(tmp, s[i])
|
> table.insert(tmp, s[i])
|
||||||
|
@ -193,10 +193,24 @@
|
||||||
> return result
|
> return result
|
||||||
>end
|
>end
|
||||||
>
|
>
|
||||||
>function test_sort_string(s)
|
>function test_sort_letters(s)
|
||||||
> check_eq(sort_string(''), '', 'test_sort_string: empty')
|
> check_eq(sort_letters(''), '', 'test_sort_letters: empty')
|
||||||
> check_eq(sort_string('ba'), 'ab', 'test_sort_string: non-empty')
|
> check_eq(sort_letters('ba'), 'ab', 'test_sort_letters: non-empty')
|
||||||
> check_eq(sort_string('abba'), 'aabb', 'test_sort_string: duplicates')
|
> check_eq(sort_letters('abba'), 'aabb', 'test_sort_letters: duplicates')
|
||||||
|
>end
|
||||||
|
- __teliva_timestamp: original
|
||||||
|
count_letters:
|
||||||
|
>function count_letters(s)
|
||||||
|
> local result = {}
|
||||||
|
> for i=1,string.len(s) do
|
||||||
|
> local c = s[i]
|
||||||
|
> if result[c] == nil then
|
||||||
|
> result[c] = 1
|
||||||
|
> else
|
||||||
|
> result[c] = result[c] + 1
|
||||||
|
> end
|
||||||
|
> end
|
||||||
|
> return result
|
||||||
>end
|
>end
|
||||||
- __teliva_timestamp: original
|
- __teliva_timestamp: original
|
||||||
append:
|
append:
|
||||||
|
|
Loading…
Reference in New Issue