Jump to content
IGNORED

2024 BASIC Tenliners Contest is calling us!!!


Recommended Posts

Just thought I'd add any little tips I find out while making a 10 liner.  This may have been posted before but I can't remember.

 

When using boleens in FastBASIC do the boleen test first will give a speed increase.

 

instead of:

 

a=a+(b=c)

 

use:

 

a=(b=c)+a

 

 

in a 10,000 loop (empty loop times at 102 jiffies) the first took 367-102=265 jiffies and the second took 336-102=234 jiffies.

 

It's only a small increase in speed but sometimes that's the difference between a steady 50fps and dropping frames.

 

 

  • Like 5
Link to comment
Share on other sites

Hi!

4 hours ago, Preppie said:

Just thought I'd add any little tips I find out while making a 10 liner.  This may have been posted before but I can't remember.

 

When using boleens in FastBASIC do the boleen test first will give a speed increase.

 

instead of:

 

a=a+(b=c)

 

use:

 

a=(b=c)+a

 

 

in a 10,000 loop (empty loop times at 102 jiffies) the first took 367-102=265 jiffies and the second took 336-102=234 jiffies.

 

It's only a small increase in speed but sometimes that's the difference between a steady 50fps and dropping frames.

 

Note that this will be true fo many expressions, in general "a = some_expression + b" is faster than "a = b + some_expression".

 

Have Fun!

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

  • 2 weeks later...

Now that I've got most of my tenliner's game logic and details done, I get to the truly hard part and contemplate a rewrite. TBXL or Fastbasic... FB does offer procedures with arguments, but unless they're local variables inside the procedure (which I suspect they're not) I'm not sure it offers any benefit for writing recursive code. @dmsc?

Link to comment
Share on other sites

Hi!

3 hours ago, OxC0FFEE said:

Now that I've got most of my tenliner's game logic and details done, I get to the truly hard part and contemplate a rewrite. TBXL or Fastbasic... FB does offer procedures with arguments, but unless they're local variables inside the procedure (which I suspect they're not) I'm not sure it offers any benefit for writing recursive code. @dmsc?

Yes, parameters in procedures are not local, so you can't call a procedure recursively and expect them to retain the value.

 

But of course, you can implement recursion if you save the values in an array, and the parameters are a good way to minimize your program in a tenliner 🙂. Do you have a recursive function that need to implement?

 

This is an example of a recursive QuickSort, using an array as a stack to store the variables that need to be preserved between calls:

 

proc QSort i0 i1
  if i1 < i0 + 10
    ' Use insertion sort for small arrays
    for i=i0 to i1-1
      temp = p(i+1)
      for j=i to i0 step -1
        if (p(j)) <= (temp) then exit
        p(j+1) = p(j)
      next
      p(j+1) = temp
    next
  else
    ' Set pivot to 'i1', do the partition
    temp = p(i1)
    j0 = i0 - 1
    j1 = i1
    do
      repeat : inc j0 :                        until (p(j0)) >= (temp)
      repeat : dec j1 : if j1 = i0 then exit : until (temp) >= (p(j1))
      if j0 >= j1 then exit
      x = p(j0) : p(j0) = p(j1) : p(j1) = x
    loop
    p(i1) = p(j0) : p(j0) = temp

    ' Recurse over smaller sub-array first
    stack1(lvl) = j0
    if i1 - j0  >  j1 - i0
      stack0(lvl) = i1   : inc lvl
      @QSort i0, j0 - 1  : dec lvl
      @QSort stack1(lvl) + 1, stack0(lvl)
    else
      stack0(lvl) = i0   : inc lvl
      @QSort j0 + 1, i1  : dec lvl
      @QSort stack0(lvl), stack1(lvl) - 1
    endif
  endif
endproc

 

The above can be minimized to:

pr.QS i j:ifj<=i t.ex.:t=p(j):k=i-1:m=j:do:r.:inck:u.p(k)>=t:r.:decm:u.m<>i a.t>=p(m):ifk>=m t.ex.:x=p(k):p(k)=p(m):p(m)=x:l.:p(j)=p(k):p(k)=t
s1(l)=k:ifj-k>m-i:s0(l)=j:incl:@QS i,k-1:decl:@QS s1(l)+1,s0(l):el.:s0(l)=i:incl:@QS k+1,j:decl:@QS s0(l),s1(l)-1:e.:en.

 

Have Fun!

  • Like 3
Link to comment
Share on other sites

Here's a little challenge using FastBASIC :)

 

I need to expand a byte into a word while doubling the bits.  eg.

 

number = 129

 

10000001 -> 11000000 00000011

 

Needs to be little endian therefore -> 00000011 11000000

 

Final decimal would be 960

 

Here's one solution:

 

n=129:b=n&128/2*3+n&64/4*3+n&32/8*3+n&16/16*3+n&8*6144+n&4*3072+n&2*1536+n&1*768

 

And here's a similar solution using a loop:

 

n=129:t=128:v=2:f.i=0to3:b=n&t/v*3+n&(t/16)*t*48+b:v=v+v:t=t/2:n.

 

 

Can anyone do any better?

 

 

Link to comment
Share on other sites

21 minutes ago, Preppie said:

Just spotted small error:

 

n=129:m=&"0123456789ABCDEF"+1:b=p.(m+n/16)+p.(m+n&15)*256

 

Needed to multiply 2nd byte 256 not first

That's why I got a negative number!!! 😂

 

42 minutes ago, Preppie said:

I thought about using a lookup table last night but when I woke up to do a bit of coding I forgot lol

Sometimes my showers are looooong while I'm trying to solve this kind of problems... 😉 

  • Haha 2
Link to comment
Share on other sites

Ok - there's a slight chance I'll have an entry, maybe in the PUR-80 category.  The game sucks, but it's something, and the big if is IF I can get it down to 10 lines.

 

I don't stand a chance to win based on the entries so far, but it will be a bucket list item completed.

Link to comment
Share on other sites

So I saw the problem posed by @Preppie but your solution and the solution by @vitoco didn't make sense to me... I'm not fluent in FastBASIC, especially "10-liner'd".

 

But I was interested so I worked out a potentially clever solution using a spreadsheet and some Python:

 

n = 129
t = [0,192,48,240,12,204,60,252,3,195,51,243,15,207,63,255]
print(256*t[n//16]+t[n%16])

 

So now, I understood vitoco's solution... at least I was on the right track.  But then I think maybe the lookup table can be replaced by an expression...

 

n = 129
f = lambda x: (x+1)//2*192-x//2*144-84*(x>3)-84*(x>11)-105*(x>7)
print(256*f(n//16)+f(n%16))

 

Now I'm realizing I'm trying to implement Preppie's solution, but he understands it better :)  I'm done here!

 

We should have a monthly 'code golf' type thing so you and the other experts can show off the chops.

 

@rdefabri good luck with your game, I bet you can make it.

 

 

 

  • Like 3
Link to comment
Share on other sites

Hi!

On 2/15/2024 at 9:23 AM, Preppie said:

Can anyone do any better?

Here is a version without a table - it is still 2 more characters than the table solution by Vitoco, but it does not use any special symbols:

 

n=x/16+x&15*256:n=n!(n*4)&13107:n=n!(n*2)&21845:n=n*3

 

The way this works is, starting with the binary number ABCDEFGH:

                         00000000ABCDEFGH
n=x/16+x&15*256          0000EFGH0000ABCD
n=n!(n*4)&13107          00EF00GH00AB00CD
n=n!(n*2)&21845          0E0F0G0H0A0B0C0D
n=n*3                    EEFFGGHHAABBCCDD

 

Have Fun!

  • Like 1
Link to comment
Share on other sites

thx, I knew you'd have something special for me :)

 

btw: we can save 2 bytes with that final n=n*3

 

x=129:n=x/16+x&15*256:n=n!(n*4)&13107:n=(n!(n+n)&21845)*3

 

I've also changed the n*2 to n+n.  This will be faster unless your compiler optimizers for this.

 

 

Link to comment
Share on other sites

Also, I realised I made a mistake in my logic.  I don't need a single word variable, I need 2 separate bytes.  I can of course do this using one of the above techniques, so now I have multiple ways of doing it I can figure out the best solution.

 

What I'm actually using this for is as follows.  I have a 2x2 gr.0 character which has a P/M overlay for the outline in a different color. I wanted to merge the character with the background image so it looked better but that would require a lot of mask data but I don't have the space for it.  Then it occurred to me that I could transform the P/M data into character data for the mask which is why I needed this little routine.  The mistake is that the character data is laid out differently so I can't dpoke the mask data into the character set data, I need to poke the individual bytes.

 

Anyway, thanks for all the help :)

  • Like 1
Link to comment
Share on other sites

Hi!

18 minutes ago, Preppie said:

thx, I knew you'd have something special for me :)

 

btw: we can save 2 bytes with that final n=n*3

Indeed! and you don't need the parenthesis, so it is now 2 chars less than the table based one:

n=x/16+x&15*256:n=n!(n*4)&13107:n=n!(n*2)&21845*3

 

Have Fun!

 

  • Like 1
Link to comment
Share on other sites

Hi!

37 minutes ago, rdefabri said:

This is probably a dumb question, but if you have multiple DATA statements, is there a way to combine them?  If so, I'm curious how the corresponding READ statements know which data to select?

 

Which BASIC?

 

For example, FastBasic does not have "READ", the data is defined as an array. You can have DATA statement span more than one line:

DATA LongVar() BYTE = 0,1,2,3,4,5,6,7,8,
DATA           BYTE = 9,10,11,12,13,14,15,16,$C0,$80,
DATA           BYTE = $FF,7,8,9


? LongVar(10)

 

For other BASIC dialects in the Atari, you can use RESTORE to assign a line to read DATA from.

 

Have Fun!

Link to comment
Share on other sites

After seeing the beautiful bit manipulation my ape brain realised that all I actually need to do is extract each bit in turn, multiply it by 3 and then put it in the correct position in the word.

 

n=129:n=n/16+n&15*16:w=1:f.i=0to7:x=x+n&w*w*3:w=w+w:n.

 

Brute force beats beauty by 1 char :)

 

edit: I have to initialize x=0 so it's not shorter :(

Edited by Preppie
  • Like 1
Link to comment
Share on other sites

Hi!

1 hour ago, Preppie said:

After seeing the beautiful bit manipulation my ape brain realised that all I actually need to do is extract each bit in turn, multiply it by 3 and then put it in the correct position in the word.

 

n=129:n=n/16+n&15*16:w=1:f.i=0to7:x=x+n&w*w*3:w=w+w:n.

 

Brute force beats beauty by 1 char :)

 

edit: I have to initialize x=0 so it's not shorter :(

You can use a REPEAT/UNTIL instead of FOR and use one less variable to do the loop, my result is in N, input in X:

i=x/16+x&15*16:w=1:n=0:R.:n=n+i&w*w*3:w=w+w:U.w>255

 

But it is smaller still if you use the same variable to hold the input and the result. This is the same length as my other solution:

n=x/16+x&15*16:I=128:R.:n=n*4+n&I/I*3:I=I+I:U.I<0

 

What kills this kind of loop is the need to invert the nibbles at the start (the "x/16=x&15*16"), without it it is much smaller.

 

Have Fun!

  • Like 1
Link to comment
Share on other sites

Yep, swapping those nybbles is a pain, so I did something without having to do the swap

 

n=129:w=1:r.:x=x+n&(w*16)/2*3+n&w*w*768:w=w+w:u.w>8

 

This save 4 chars over your last one :)  but maybe some of your magic bit manipulation can shrink it even further.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...