Log In  

Been working on a Tweetcart mimicking the old lines screensavers, and I've managed to get it pretty small--it's about 300 characters when all of the spaces are removed, but now I'm stuck, and can't figure out a way to shrink it any further.

Here's where I'm at so far:

a,b,c,d={},rnd,128,flr
for i=1,5 do
  a[i]={x=b(c),y=b(c),w=b(c),h=b(c),p=d(b(4)),z=d(b(4)),l=i+7,m=mid,t=c}
end
::_::
for _=1,1000 do pset(b(c),b(c),0) end
for _𝘦𝘯𝘷 in all(a) do
  d={[0]=1,-1,-1,1}
  line(x,y,w,h,l)
  x+=d[p]
  y+=d[(p-1)%4]
  w+=d[z]
  h+=d[(z-1)%4]
  p,z=x+y!=m(0,x,t)+m(0,y,t)and(p+1)%4or p,w+h!=m(0,w,t)+m(0,h,t)and(z+1)%4or z
end
flip()
goto _

This renders a result I'm happy with:

But it's just ~60 characters too long. :( Any one have any advice or suggestions on ways to reduce it further? I feel like there have to be some minimization techniques I'm missing.

P#139499 2024-01-01 19:17

3

I think you cut eight characters by changing your first for loop like this:

a,b,c={},rnd,128
for i=1,5 do
  a[i]={x=b(c),y=b(c),w=b(c),h=b(c),p=b(4)\1,z=b(4)\1,l=i+7,m=mid,t=c}
end

The cut is mostly not defining d as flr and using the \1 notation for integer division instead.

You may also not need the t=c assignment in your a table in the loop. Since it doesn't look like you're changing the value of t anywhere, you could just use c directly and that would cut another 4 characters.

P#139500 2024-01-01 19:55 ( Edited 2024-01-01 20:35)
1

beat me to it @2bitchuck!

@sizescape have you looked at using foreach instead of for in all()? I know usage would need to be quite different so I'm not sure if there's a net gain to be had there.

I'm sure that if it were shorter to define your own mid function with 0 and t (or c) hard-coded that you would have already done so.. but maybe there's a trick for that.

Same for using _draw, I don't suppose that's shorter than what you're using now.

You could save one character by opting for 999 black pixels per frame instead of 1000 ;)

P#139504 2024-01-01 21:54

Thanks @2bitchuck! Unfortunately, the t=c is needed, since overriding _ENV hides the global variables.

And @kozm0naut: Yeah, using functions makes things longer.

The current edge-collision detection code:

  p,z=x+y!=m(0,x,t)+m(0,y,t)and(p+1)%4or p,w+h!=m(0,w,t)+m(0,h,t)and(z+1)%4or z

is 77 characters, compared to

  function g(a,b,c) return a+b!=m(0,a,t)+m(0,b,t)and(c+1)%4or c end
  p,z=g(x,y,p),g(w,h,z)

Which comes in at 86. Similar problem comes up with foreach, since I'd have to define a function, which adds in the function, and end keywords--11 extra characters.

With your suggested changes, and changing the delta lookup-table to just be some bit manipulation, I was able to get a little further:

a,b,c={},rnd,128
for i=1,5 do
  a[i]={x=b(c),y=b(c),w=b(c),h=b(c),p=b(4)\1,z=b(4)\1,l=i+7,m=mid,t=c}
end
::_::
for _=1,999 do pset(b(c),b(c),0) end
for _𝘦𝘯𝘷 in all(a) do
  line(x,y,w,h,l)
  x+=1-((p+1)&2)
  y+=1-(p&2)
  w+=1-((z+1)&2)
  h+=1-(z&2)
  p,z=x+y!=m(0,x,t)+m(0,y,t)and(p+1)%4or p,w+h!=m(0,w,t)+m(0,h,t)and(z+1)%4or z
end
flip()
goto _

Now it's just 41 characters too long to tweet after removing spaces.

P#139523 2024-01-02 06:51 ( Edited 2024-01-02 06:52)
1

I found something for you:
https://www.lexaloffle.com/bbs/?pid=49823

Seems we can drop the 0 argument from the mid calls altogether! Just a few tokens, but it's something.

P#139641 2024-01-04 17:47
1

2 bytes :
The ,0 of the pset statement could be omitted if the last line drawn had been black. This can be done by having l (the color parameter in lines) go from -5 to 0

for i=1,6 do
  a[i]={x=b(c),y=b(c),w=b(c),h=b(c),p=b(4)\1,z=b(4)\1,l=i-6,m=mid,t=c}
end

You may or may not prefer the old colours.

4 bytes from abusing the relative priorities of & and + :

  x+=1-(p+1&2)
  y+=1-(p&2)
  w+=1-(z+1&2)
  h+=1-(z&2)

This looks very wrong

P#140204 2024-01-16 14:39 ( Edited 2024-01-16 14:41)
1

@RealShadowCaster: Yeah, not a fan of the different colors. :(

Priority abuse inspired something else--I can use masks for doing the edge collision checks, instead of mid, if I make all of the positions integers, and I don't really need to constraint p and z to be in the range 0-3.

Brings it down to

a,b,c={},rnd,128
for i=1,5 do
  a[i]={x=b(c)\1,y=b(c)\1,w=b(c)\1,h=b(c)\1,p=b(4)\1,z=b(4)\1,l=i+7,t=c}
end
::_::
for _=1,999 do pset(b(c),b(c),0) end
for _𝘦𝘯𝘷 in all(a) do
  line(x,y,w,h,l)
  x+=1-(p+1&2)
  y+=1-(p&2)
  w+=1-(z+1&2)
  h+=1-(z&2)
  p+=x&t|y&t>0 and 1or 0
  z+=w&t|h&t>0 and 1or 0
end
flip()
goto _

Just 1 character to go (after spaces are removed)!

a={}b,c=rnd,128for i=1,5do a[i]={x=b(c)\1,y=b(c)\1,w=b(c)\1,h=b(c)\1,p=b(4)\1,z=b(4)\1,l=i+7,t=c}end::_::for _=1,999do pset(b(c),b(c),0)end for _𝘦𝘯𝘷 in all(a)do line(x,y,w,h,l)x+=1-(p+1&2)y+=1-(p&2)w+=1-(z+1&2)h+=1-(z&2)p+=x&t|y&t>0and 1or 0z+=w&t|h&t>0and 1or 0end flip()goto _
P#140248 2024-01-17 04:38 ( Edited 2024-01-17 05:55)
2

@sizescape,

Nice trick with the binary 'or' operators, might have to use that elsewhere.

Used the tonum() boolean feature and got it down to 275 chars.

a={}b,c=rnd,128for i=8,12do
add(a,{x=b(c)\1,y=b(c)\1,w=b(c)\1,h=b(c)\1,p=b(4)\1,z=b(4)\1,l=i,t=c})end::_::for
_=1,999do pset(b(c),b(c),0)end
for _ENV in all(a)do
line(x,y,w,h,l)x+=1-(p+1&2)y+=1-(p&2)w+=1-(z+1&2)h+=1-(z&2)p+=tonum(x&t|y&t>0)z+=tonum(w&t|h&t>0)end
flip()goto _

And it actually seems to work basically the same without flooring the initial values (263 chars)

a={}b,c=rnd,128for i=8,12do
add(a,{x=b(c),y=b(c),w=b(c),h=b(c),p=b(4),z=b(4),l=i,t=c})end::_::for
_=1,999do pset(b(c),b(c),0)end
for _ENV in all(a)do
line(x,y,w,h,l)x+=1-(p+1&2)y+=1-(p&2)w+=1-(z+1&2)h+=1-(z&2)p+=tonum(x&t|y&t>0)z+=tonum(w&t|h&t>0)end
flip()goto _
P#140250 2024-01-17 05:38 ( Edited 2024-01-17 05:57)

@JadeLombax Thank you! Yay!

P#140251 2024-01-17 05:56 ( Edited 2024-01-17 05:59)

Thanks everyone for your help! In case anyone reading the thread is interested in my thought process, here's a version of the cart with longer variable names, and comments describing what's happening:

lines={}
-- Initialize 5 colored lines at random positions
for i=1,5 do
  lines[i]={
    x1=rnd(128),
    y1=rnd(128),
    phase2=rnd(4),
    x2=rnd(128),
    y2=rnd(128),
    phase1=rnd(4),
    clr=i+7, -- colors 8-12 look nice
  }
end

::start::

-- Draw 999 black dots, to fade out previous frames' lines.
for _=1,999 do 
  pset(rnd(128),rnd(128),0) 
end

-- By assigning elements of lines to _𝘦𝘯𝘷, we don't need to use
-- dot notation to access the members of each table.
-- See www.lexaloffle.com/bbs/?tid=49047 for more details.
for _𝘦𝘯𝘷 in all(lines) do

  -- Draw the line
  line(x1,y1,x2,y2,clr)

  -- Each of the endpoints of the lines should be incremented, with
  -- the phase selecting how.
  --   Phase[0], move left  and down: ( 1, 1)
  --   Phase[1], move right and down: (-1, 1)
  --   Phase[2], move right and up  : (-1,-1)
  --   Phase[3], move left  and up  : ( 1,-1)
  --
  -- Note: Since the phase only increases, if an endpoint is moving
  -- the 'wrong' way, it might need to make 3 left turns, instead of
  -- 1 right turn to get back in bounds. When I showed the demo to a
  -- few people, nobody noticed until I pointed it out, and even then
  -- they didn't mind, so this is fine.
  --  
  -- Easier to explain the following math for y:
  --   if the phase is 0,1 want 1
  --   if the phase is 2,3 want -1
  -- 
  -- Can compute this with:
  --  1 = 1-0
  -- -1 = 1-2
  -- 
  -- If we generate a 2 when phase is 2 or 3, which we can
  -- do by selecting bit 2 with "&2"
  --
  -- Since x's pattern is y's shifted by 1, just add 1 to phase, and
  -- do the same computation.
  x1+=1-(phase1+1&2)
  y1+=1-(phase1&2)
  x2+=1-(phase2+1&2)
  y2+=1-(phase2&2)

  -- Want to bounce if we hit the edge of the screen, i.e.:
  --
  -- if x less than zero or
  --    x greater than 127 or
  --    y less than zero or
  --    y greater than 127 then
  --   go to the next phase step
  -- 
  -- Since the 7th bit of the number will be set when it's first
  -- negative or greater than 127, only need to check that to know
  -- we should advance the phase, and 'turn'. 
  phase1+=tonum(x1&128|y1&128>0)
  phase2+=tonum(x2&128|y2&128>0)

end

-- Slow down the animation to 30fps before looping.
flip()
goto start

And the minimized (262 char) version:

a={}b,c=rnd,128for i=1,5do a[i]={x=b(c),y=b(c),w=b(c),h=b(c),p=b(4),z=b(4),l=i+7,t=c}end::_::for _=1,999do pset(b(c),b(c),0)end for _𝘦𝘯𝘷 in all(a)do line(x,y,w,h,l)x+=1-(p+1&2)y+=1-(p&2)w+=1-(z+1&2)h+=1-(z&2)p+=tonum(x&t|y&t>0)z+=tonum(w&t|h&t>0)end flip()goto _

Creates:

P#140292 2024-01-18 06:34 ( Edited 2024-01-18 06:36)

[Please log in to post a comment]