Working on trying to understand RLE and I found a simple algorithm which I converted to pico-8 lua. When I run it however it seems like the while loop exits and executes the next line of code every iteration even though the conditions are still being met. I'm not sure what is going on, but I am sure that it is my fault. :D
cls() string='wwwwweehhhhhhhjjiiioop' function print_rle(str) local string=str local n=#string local j=0 for i=1,n do local char_count=1 while i<n-1 and sub(string,i,_)==sub(string,i+1,_) do char_count+=1 i+=1 end print(sub(string,i,_)..char_count,8*j,10,7) j+=1 end end print_rle(string) |
Hello, @ghandolhagen:
I am not seeing you define _
as a variable so unless I am mistaken it will be NIL, meaning not defined and you cannot add or subtract values to it nor add string characters to it - until it is defined.
I found by changing your _
to variable i
that it runs without overlapping the text.
Thank you for taking a look. I purposely did not define the stop position for the sub() so that it would only return the character at the start position (the manual has a bit about this) since it should be counting runs and only returning one character plus a number.
For instance the expected string is: w5e2h7j2i3o2p1
Currently returns:
w5w4w3w2w1e2e1h7h6h5h4h3h2h1j2j1i3i2i1o2o1p1
Which is pretty much the exact opposite of run length encoding. LOL XD So there is definitely a problem with my logic somewhere. Again I appreciate the extra pair of eyes.
Oh ! If it was purposeful, @ghandolhagen, then there is no reason to include the argument. You can use sub(string,pos,[optional])
That's the nice thing about modern Pico-8. You can leave out arguments, there is no need to define them as NIL.
So sub(string,i,_)
can be shortened to sub(string,i)
you’re using something added in 0.2.4 and removed in 0.2.5:
> Changed: sub(str, pos, nil) returns whole string (pre-0.2.4 behaviour). For single chars, can now use str[pos].
Rewrote the algorithm for the latest pico-8, but the logic problem remains.
Far from compressing the string it returns the same bloated string. I suspect the problem lies in the for loop and i not getting updated in it from the while loop. But that still doesn't explain the apparent early breakout of the loop when conditions are still being met.
new code:
cls() string_to_compress="wwwwwiiidddddddkkkkkssssllwwwwoooooppp" function compress(str) local str=str local len=#str local table={} local table_str="" for i=1,len do local char_count=1 local run_str="" while i<len-1 and sub(str[i])==sub(str[i+1]) do char_count+=1 i+=1 end run_str=run_str..sub(str[i])..char_count add(table,run_str) end for i=1,#table do table_str=table_str..table[i] end return table_str end compressed_str=compress(string_to_compress) print(compressed_str,0,0,7) |
In lua, for loops are precalculated for speed. the i from the for loop is reset to the next value as dictated by the for loop itself after each iteration.
If you want i to be iterated by the while loop, then both loops need to be while loops.
@kimiyoribaka Good to know. I'll give that a try. I appreciate it.
That was it! Brilliant! One weird thing though that I don't understand is that I had to i+=1 twice (actually I know why. Except for the first while loop all other "i"s are local to the scope of their respective loops.), but hey I'm not complaining RLE is working. Thanks very much for the insight!
cls() string_to_compress="wwwwwiiidddddddkkkkkssssllwwwwoooooppp" function compress(str) local str=str local len=#str local table={} local table_str="" local i=1 while i<len do local char_count=1 local run_str="" while i<len-1 and sub(str[i])==sub(str[i+1]) do char_count+=1 i+=1 end run_str=run_str..sub(str[i])..char_count add(table,run_str) i+=1 end for i=1,#table do table_str=table_str..table[i] end return table_str end compressed_str=compress(string_to_compress) print(compressed_str,0,0,7) |
[Please log in to post a comment]