This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
BlackMenthol's profile picture

[Lua] Alphabetical order function shuts down the computer

Started by BlackMenthol, 13 April 2013 - 06:28 AM
BlackMenthol #1
Posted 13 April 2013 - 08:28 AM
Hi guys, sorry this is the second topic I opened in few days, but I'm working at a big project (big for me,lol) and I'm encountering some problems every step.

So i'm working at a sorting sistem (with the Interactive sorter from Miscperipheral), and I'm trying to write a script for a menu with a search field to search, call and retrieve items.
So everytime I type for example "c", I want a list to appear of all items starting with the letter "c" and so on. And I want that lis to be in alphabetical order.

So this is What I wrote until now: http://pastebin.com/zjtyj7ue . It's obviously not finished yet, but i'm getting there.

My problem is with the alphaList() function, as I said I want the list to be in alphabetical order:


function alphaList()
  for k,v in pairs(nameList) do  -- take every "v" one of the time from a table where items are in order of id
	local inserted = false
	if alphaNameList ~= {} then -- check if the table is empty i.e. nothing has been inserted yet
	  for key,vi in pairs(alphaNameList) do -- if is not empty for every "v" check every "vi" in the new table until it find one that is after in the alphabetical order and then put it one step down (key - 1)
		if v < vi then
		  table.insert(alphaNameList,key - 1,v)
		  inserted = true
		end
	  end
	end  
	if inserted == false then -- if "v" is bigger of any "vi" or in the case table was empty, inserted is still false so it's going to simply put it at the end of the table
	  table.insert(alphaNameList,v)
	end
  end		  
end

I'm trying to take elements from the nameList table (those are sorted for ID order, so [1]="Stone",[3]="Dirt",[4]="Cobblestone" etc.) and putting them in the alphaNameList table in alphabetical order.
I know there is a function in the table api (table.sort) and I read some info about it on the web, but because i'm still not to much an expert and because english = not nativeLanguage, I didn't understand how to use for this kind of situations.

So I tryed to go around the problem with this function.

Long story short, when I call this function the computer shuts down with no error message at all.
Any idea why? too many cycles? Did I totally misunderstood how "for k,v in pairs(table)" works? Is it a conspiracy? Am I going to survive the night? :P/>

thanks for the help :D/>

P.S. nameList contains about 100 elements and yes, I'm receiving correctly the table from rednet, I already tested it.
Lyqyd #2
Posted 13 April 2013 - 08:59 AM
Give this a whirl:


function sortedSubsetList(listTable, matchString)
  local matchTable = {}
  for k, v in pairs(listTable) do
    if string.match(v, matchString) then
      table.insert(matchTable, v)
    end
  end
  table.sort(matchTable)
  return matchTable
end

I'm not sure what your insertion sort was doing to break things (having not read the code in great gory detail), but I wouldn't be surprised if it was tripping the yield protection.
BlackMenthol #3
Posted 13 April 2013 - 09:25 AM
so… yeah… riight.. what exactly is matchstring supposed to be ? a pattern? :(
LBPHacker #4
Posted 13 April 2013 - 09:30 AM
Try this:
Spoiler


local chars = {}
for i = 32, 126 do chars[string.char(i)] = i end
--[[ You can redefine this table, but this way the entries will be sorted by ASCII values.
     So "A" (0x41) will be before "B" (0x42), but "a" (0x61) will be after "C" (0x43) ]]

local function sortingComparsion(valueA, valueB)
    --[[ This is like strcmp in C++. Not sure if the return values are
         correct or not though. I mean, not sure if strcmp returns +1
         or -1 if the first argument is lower.

         The function itself works though... ]]
    local strpos = 0
    local difference = 0
    while strpos < #valueA and strpos < #valueB and difference == 0 do
        strpos = strpos + 1
        if chars[string.sub(valueA, strpos, strpos)] > chars[string.sub(valueB, strpos, strpos)] then
            difference = 1
        elseif chars[string.sub(valueA, strpos, strpos)] < chars[string.sub(valueB, strpos, strpos)] then
            difference = -1
        end
    end
    if difference == -1 then
        return true -- return true if we want valueA to be before valueB
    else
        return false -- or return false if we want valueB to be before valueA
    end
end

local t = {"kiwi", "banana", "appke" --[[Note that the 4th letter is a K]], "potato", "apple"}
print(table.concat(t, ", "))
table.sort(t, sortingComparsion)
print(table.concat(t, ", "))

The function we give table.sort returns true if we want the first given argument to be before the second, and returns false if we want it vice-versa.
BlackMenthol #5
Posted 13 April 2013 - 10:01 AM
Give this a whirl:


function sortedSubsetList(listTable, matchString)
  local matchTable = {}
  for k, v in pairs(listTable) do
	if string.match(v, matchString) then
	  table.insert(matchTable, v)
	end
  end
  table.sort(matchTable)
  return matchTable
end

I'm not sure what your insertion sort was doing to break things (having not read the code in great gory detail), but I wouldn't be surprised if it was tripping the yield protection.

So ok, after looking at this and not quite getting it, I just realized that table.sort it's easier than I thought.
so I just did this:


for k,v in pairs(nameList) do
	table.insert(alphaNameList,v)
end
table.sort(alphaNameList)
  
And it works. I feel stupid now :/

Thanks for your time :P
Lyqyd #6
Posted 13 April 2013 - 11:00 AM
The matchString piece was for the filter-as-you type thing you had mentioned earlier. That would match characters at any point in the strings (so "stone" matches "cobblestone" and "stone brick"). You just pass in whatever they have typed so far as matchString. This also lets them use Lua patterns to do advanced searches with no additional effort on your part.

You'd run that function against your entire list the first time, then against the sorted list for each subsequent keystroke.
BlackMenthol #7
Posted 13 April 2013 - 01:47 PM
oh ok, that's why i couldn't understand that. I thought I was supposed to use it for the alphabetical order only, and the fact that the function was asking me one string at a time made me confused.

Yeh i was thinking to do that "my way", splitting strings in single characters and checking letter by letter with some if statement and a bunch of cycle (so get the first input, check the first letter of every elements in the list, filter the matched one out, and reapeat with the second input etc.), but your function is definetely easier and more clean.

Only problem, if i'm getting it right, it's gonna pick results that contains the matchstring without consider the position in the string, and I like the idea of "stone" matching with "cobblestone" , but not the idea of "e" matching with "cake" for example. I need to consider that.
But enough spoilers from the pros, I want to figure it out by myself :P

Lua wiki, here I come