Log In  

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)
P#118567 2022-10-05 01:13

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.

P#118572 2022-10-05 03:02

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.

P#118574 2022-10-05 03:37
1

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)

P#118577 2022-10-05 04:00
1

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].

https://www.lexaloffle.com/dl/docs/pico-8_changelog.txt

P#118620 2022-10-05 15:24

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)
P#118738 2022-10-07 19:05 ( Edited 2022-10-07 20:22)
1

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.

P#118743 2022-10-07 20:36

@kimiyoribaka Good to know. I'll give that a try. I appreciate it.

P#118744 2022-10-07 20:40

@kimiyoribaka

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)
P#118764 2022-10-08 00:33 ( Edited 2022-10-08 00:36)

[Please log in to post a comment]