Author Topic: Scramble/Boggle Lua  (Read 11644 times)

0 Members and 1 Guest are viewing this topic.

Offline cyanophycean314

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 363
  • Rating: +43/-1
  • It's You!
    • View Profile
Scramble/Boggle Lua
« on: June 30, 2012, 02:53:49 pm »
Because I recently got Scramble with Friends for my Android tablet, I took it upon myself to make this game. Right now, the screenshot shows most of what it can do. I may enter this for the contest if I can code an AI to be your "friend." You'll have the option to watch him play.

Right now the biggest problem is the dictionary. I've googled online for a dictionary and it was 170,000+ words. I tried to put that into my Lua file, but it said there was not enough memory  :P. So the dictionary right now is all the words I can think of.

I still need to add a solver to find all possible words, change the scoring scheme to be more like Scramble (without double/triple), add some results page, randomly generated puzzles, and get the dictionary working.

Hope you guys enjoy.

Offline Adriweb

  • Editor
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1708
  • Rating: +229/-17
    • View Profile
    • TI-Planet.org
Re: Scramble/Boggle Lua
« Reply #1 on: July 01, 2012, 09:46:24 am »
Very nice ! :D
My calculator programs
TI-Planet.org co-admin.
TI-Nspire Lua programming : Tutorials  |  API Documentation

Offline shmibs

  • しらす丼
  • Administrator
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2132
  • Rating: +281/-3
  • try to be ok, ok?
    • View Profile
    • shmibbles.me
Re: Scramble/Boggle Lua
« Reply #2 on: July 01, 2012, 11:08:14 am »
would using some form of text compression slow things down too much, or would that plus a binary search be doable?
* shmibs has no clues about the speed of nspire lua
« Last Edit: July 01, 2012, 11:08:32 am by shmibs »

Offline Jim Bauwens

  • Lua! Nspire! Linux!
  • Editor
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1881
  • Rating: +206/-7
  • Linux!
    • View Profile
    • nothing...
Re: Scramble/Boggle Lua
« Reply #3 on: July 01, 2012, 12:48:49 pm »
Adding compression should not slow it down much.
Anyway, how do you store the data ? Just a large table ?

Offline cyanophycean314

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 363
  • Rating: +43/-1
  • It's You!
    • View Profile
Re: Scramble/Boggle Lua
« Reply #4 on: July 01, 2012, 03:52:14 pm »
Currently all the dictionary is stored in a table, and I don't really know a better way to do that. I have binary search implemented so speed shouldn't be a problem, hopefully. I have no idea about compression...

Offline Loulou 54

  • LV4 Regular (Next: 200)
  • ****
  • Posts: 165
  • Rating: +39/-0
    • View Profile
    • Mes programmes sur TI bank.
Re: Scramble/Boggle Lua
« Reply #5 on: July 21, 2012, 09:34:01 am »
Hello cyanophycean !

In TI-Translate, I stored the data in huge strings IN the TI Nspire document. (indeed I couldn't paste all into ONE string because the length of a string on the TI Nspire is limited ! So I had to split my list into small pieces ! (516 words per string if I remember, or 516*84 characters)) That was rather complicated and I had to make a kind of a script to automate "copy/paste"s from notepad to the student software.. %)
Why such a weird and difficult solution ?
Because my strings contained a lot of accentuated characters and the TI Nspire scripting tool made shit.. (just closed the Student Software every time I pasted the code !)
(I also tried with Luna, and the generated file produces an error too..)

About memory problems : my biggest version (english/french) contains 58 959 words from english to french AND 56 252 words from french to english. Moreover, the storage isn't really optimized... Actually each word takes exactly 84 characters and the remaining place is filled with blanks.
An extract :
Quote
a b c {m} [abécédaire]         primer {n} [ABC]                                     a latere [REL‚ loc adj]        a latere [adj phr]                                   a latere [REL‚ loc adv]        a latere [adv phr]                                   a priori [loc adj]             a priori [adj]                                       a priori [loc adv]             a priori [adv], guess; at a ~ [adv phr]              a priori {m inv}               apriorism {n}, preconception {n}                     A {m} [alphabet latin]         A {n} [Roman alphabet]                               A {n} [ÉLEC‚ ampère]           amp {n} [ELEC‚ an ampere]                            abaissement {m}                abatement {n}, decay {n}, lowering {n}               abaisser [v tr]                lower [v tr‚ make lower]                             abaisser [v tr‚ raccourcir]    cut up [v tr]                                        abaisser [v tr‚ réduire]       bring down [vt‚ lower a price]                       abaisser; s'~ [v pr]           off; to get ~, demean; to ~ oneself                  abaisser; s'~ vivement [v pr]  duck down [v intr]                                   abaisser; s'~ à faire          stoop; to ~ to doing                                

This was the original format of the data from Freelang dictionnaries. On the other side, this format was convenient to navigate through the list because you just have to make 84 characters steps to get the next word ! :)

So, here is how it works for my TI translate ! ^^

In term of number of characters, it represents for both lists 9 677 724 characters !

So if you want to solve your problem, maybe you could do as I did, but I don't think that's the best solution. Moreover you don't need here the assets of this solution, as I did. (storing in a string to ease the string research, supporting accentuation,...)

So I think that the easier solution is to reduce the amount of word ! :P

PS : have you tried to split your table into smallest ones ? (maybe it's the length of a table wich is limited..)

Anyway, good luck ! :D

EDIT :
Your program must search words in your list actually ? How do you do that with your table ? You scan the whole table to see if it contains the word ?
« Last Edit: July 21, 2012, 09:39:38 am by Loulou 54 »
Some of my program available here.. :)
http://ti.bank.free.fr/index.php?mod=archives&ac=voir2&id=1471

     

Offline cyanophycean314

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 363
  • Rating: +43/-1
  • It's You!
    • View Profile
Re: Scramble/Boggle Lua
« Reply #6 on: July 21, 2012, 09:59:42 am »
Thanks Loulou for the explanation and suggestions.  :)

I'll try splitting up my table into smaller ones, probably divided by letters. Or I could also use strings like you did.

I planned on using binary search to go through my list and find the word, but now I just realized that there were string search functions provided by Lua.

Offline Nick

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1166
  • Rating: +161/-3
  • You just got omnom'd
    • View Profile
    • Nick Steen
Re: Scramble/Boggle Lua
« Reply #7 on: July 22, 2012, 05:26:00 am »
wow, this is a great game :o maybe you could just use semicolons (;) to split words, and the look for the matching ; so split them up, that would be the most easy way i think..

is it correct if i saw that you don't get extra points if you make a word you already formed, or did i just look bad?

how do you make the grid? because you say 'randomly generate ouzzles', does that mean you now just make them by hand and type them in?

Offline cyanophycean314

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 363
  • Rating: +43/-1
  • It's You!
    • View Profile
Re: Scramble/Boggle Lua
« Reply #8 on: July 23, 2012, 09:07:34 am »
Thanks.  :)

What exactly do you mean when you said to use semicolons to split words? To select words, you press the tab button, and then use the numpad to move along the board, selecting letters as you go. Then you release tab, and that's your word.

The program checks if you've already used that word.  :)

Currently this is just a hard-coded grid, but I'm working on random generation (balancing it is kinda tricky...).

Edit: Woah, it's my 300th post.
« Last Edit: July 23, 2012, 09:08:17 am by cyanophycean314 »

Offline Nick

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1166
  • Rating: +161/-3
  • You just got omnom'd
    • View Profile
    • Nick Steen
Re: Scramble/Boggle Lua
« Reply #9 on: July 23, 2012, 05:50:07 pm »
i meant that semicolon thing for your encoding of the library.

if you do for example lib = "can;pie;cake;board;door" etc you can easely split them up to find the words, and you don't need that endlessly long table to store your entries..

Offline Loulou 54

  • LV4 Regular (Next: 200)
  • ****
  • Posts: 165
  • Rating: +39/-0
    • View Profile
    • Mes programmes sur TI bank.
Re: Scramble/Boggle Lua
« Reply #10 on: July 23, 2012, 06:31:53 pm »
binary search == dichotomy ?

i meant that semicolon thing for your encoding of the library.

if you do for example lib = "can;pie;cake;board;door" etc you can easely split them up to find the words, and you don't need that endlessly long table to store your entries..

Yes it could be a good solution, using the string.find function. :)
(Actually that's almost what I did for TI translate, but in Basic.)

Moreover this function provides very powerful features with what's called "patterns". You can look in the Lua manual to get more informations. :)

(little trick : if you want to convert your table into Nick's format, don't forget the "Replace" function of your notepad ! ;) I mean, for example : {"hello","world","I'm happy"} => Replace `","` by `;` => {"hello;world;I'm happy"} => then just delete the "{" and you have your string :) )
« Last Edit: July 23, 2012, 06:33:31 pm by Loulou 54 »
Some of my program available here.. :)
http://ti.bank.free.fr/index.php?mod=archives&ac=voir2&id=1471

     

Offline 3rik

  • LV3 Member (Next: 100)
  • ***
  • Posts: 92
  • Rating: +8/-0
  • My TI-84+ SE
    • View Profile
Re: Scramble/Boggle Lua
« Reply #11 on: July 23, 2012, 08:02:43 pm »
If the plan is to have large dictionaries, this might be useful.  :)

Code: [Select]
function editDictionary(dictionary, old_dict)
local data = old_dict or {}
for _, word in ipairs(dictionary) do
local curchar = data
for i = 1, #word do
local char = word:sub(i, i)
if not curchar[char] then
curchar[char] = {endof = i == #word and true or nil}
elseif not curchar[char].endof then
curchar[char].endof = i == #word and true or nil
end
curchar = curchar[char]
end
end
data.lookup = function(tbl, str)
local function lookup(str)
local curchar = data
for i = 1, #str do
curchar = curchar[str:sub(i, i)]
end
return curchar.endof
end
err, ret = pcall(lookup, str)
return err and ret or nil
end
return data
end

It takes a table like
Code: [Select]
list={"carbon","cars","car","cat","cats"}

and creates a table like
Code: [Select]
dictionary = {
c={
a={
r={
b={
o={
n={endof = true}
}
}
s={endof = true}
endof = true
}
t = {
s={endof = true}
endof = true
}
}
}
lookup = function(tbl, str)
--blah blah blah
end
}



lookup takes a string and rapidly returns a true or nil value based on if the word is in the list of acceptable words.

Here's an example:
Code: [Select]
dict = {"cat", "cats", "dog", "mouse"}

dictionary = editDictionary(dict)

print("d:", dictionary:lookup("d"))
print("do:", dictionary:lookup("do"))
print("dog:", dictionary:lookup("dog"))
print("dogs:", dictionary:lookup("dogs"))
print("dogz:", dictionary:lookup("dogz"))

amendment = {"dogs"}
dictionary = editDictionary(amendment, dictionary)
print("\nAmendment: dogs added!\n")

print("d:", dictionary:lookup("d"))
print("do:", dictionary:lookup("do"))
print("dog:", dictionary:lookup("dog"))
print("dogs:", dictionary:lookup("dogs"))
print("dogz:", dictionary:lookup("dogz"))

prints

Code: [Select]
d: nil
do: nil
dog: true
dogs: nil
dogz: nil

Amendment: dogs added!

d: nil
do: nil
dog: true
dogs: true
dogz: nil

What I like about this way is that it narrows the search down for each letter in the string instead of searching for the whole string in a giant table or string. It could be potentially bulky, though.

Worst case scenario, it could end up indexing something like dictionary.p.n.e.u.m.o.n.o.u.l.t.r.a.m.i.c.r.o.s.c.o.p.i.c.s.i.l.i.c.o.v.o.l.c.a.n.o.c.o.n.i.o.s.i.s.endof but most of that searching would be handled by Lua itself.

This is case sensitive, but if it makes a difference it would only take a simple metatable to fix.


EDIT: Reread the first post and testing a few things first
« Last Edit: July 23, 2012, 08:08:32 pm by 3rik »
Userbars

Offline cyanophycean314

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 363
  • Rating: +43/-1
  • It's You!
    • View Profile
Re: Scramble/Boggle Lua
« Reply #12 on: July 23, 2012, 09:14:47 pm »
@3rik: Your solution is interesting, but I think memory constraints will occur... I'll give it a try if my current attempt fails.

Right now, I have around 1158 strings with format: words1 = 'aa;aah;aahed;' words2 = 'aahing;aardvark;'
The problem is that I want to go through the different strings. My current code is this:
Code: [Select]
function checkWord(word)
local letterkeys = {1,72,129,241,310,360,402,437,479,533,541,551,582,647,679,720,822,827,895,1019,1076,1112,1130,1152,1153,1155}
jstart = letterkeys[string.byte(word) - string.byte('a') + 1]
for i = jstart,1158 do
loadstring("abc = words"..i)
if string.find(abc,word) then
return true
end
end
return false
end

The letterkeys indexes a place for each letter, so the searching will go faster. Then it starts at that index and goes through each string and searches it using the string.find().

The loadstring thing doesn't work. It's purpose is to try and execute
Code: [Select]
abc = words12or
Code: [Select]
abc = words13depending on the value of i. This way I can avoid a big table that'll probably give me memory errors. It's basically like indexing without a big master table without a huge variable.

I'm not too familiar with loadstring, but it seems very powerful if it can be used like this.

Offline 3rik

  • LV3 Member (Next: 100)
  • ***
  • Posts: 92
  • Rating: +8/-0
  • My TI-84+ SE
    • View Profile
Re: Scramble/Boggle Lua
« Reply #13 on: July 23, 2012, 10:57:29 pm »
I tested this way on the student software and it took about 3 seconds to load my list of ~100,000 words and convert it to the table. From there it was able to index any word very quickly (including long words like symptomatologically). The overall memory is a tad bulky (but there's only so much you can shrink 100,000 words). Each key, however, only points to a table containing, at most, 27 new keys.

A warning: don't paste tables like this into programs bulky IDEs with syntax highlighting. I pasted a table into the student software, walked away for an hour, came back and it was still trying to highlight everything. I eventually gave up and used the old scripting tools to test out the method.

I'll attach the code I tried with.

EDIT: I just realized that there are two lists in this program. There is still a table with all 100,000 words in it. I haven't sent this code to my calculator, so I'm not 100% sure that there won't be any memory issues.

EDIT2: I just realized, if one wanted definitions included with this structure, the values of the endofs (or _s) would just need to be changed from true to the definition. This wouldn't really apply to Boggle, but it could be used elsewhere.

EDIT3: loadstring is intended to be more for accepting code from the user. oclua is a good example of this. Tables and strings should be able to handle this problem without loadstring.
« Last Edit: July 24, 2012, 12:57:37 pm by 3rik »
Userbars

Offline Nick

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1166
  • Rating: +161/-3
  • You just got omnom'd
    • View Profile
    • Nick Steen
Re: Scramble/Boggle Lua
« Reply #14 on: July 24, 2012, 12:22:03 pm »
A warning: don't paste tables like this into programs with syntax highlighting. I pasted a table into the student software, walked away for an hour, came back and it was still trying to highlight everything. I eventually gave up and used the old scripting tools to test out the method.

you probably never heard of notepad++ ?? it takes 0.00001 seconds to load, and it only loads the parts you see, so as you scroll it colors the part you see, so no unnecessary coloring happens :)