IGNORED

# 2024 BASIC Tenliners Contest is calling us!!!

## Recommended Posts

Key info:

- Deadline: Saturday, March 16, 2024, 18:00 CET

- Awards Ceremony: Saturday, April 6, 2024

• 6
• 1
##### Share on other sites

Cool, guess I'll have to  put a pause on learning Defold.

##### Share on other sites

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.

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

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

`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!

• 1
• 1
##### Share on other sites

Thx, I figured that would be the case but didn't do full testing.

##### 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?

##### 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!

##### 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?

##### Share on other sites

54 minutes ago, Preppie said:

Can anyone do any better?

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

The string actually is this sequence of chars/bytes: \$00,\$03,\$0C,\$0F,\$30,\$33,\$3C,\$3F,\$C0,\$C3,\$CC,\$CF,\$F0,\$F3,\$FC,\$FF

##### Share on other sites

Thanks Vitoco

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

##### Share on other sites

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

Edited by Preppie
##### 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... 😉

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

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

##### 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!

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

##### 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

##### 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!

##### Share on other sites

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?

##### 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!

##### Share on other sites

I've just spent an hour trying to figure out exactly what's going on with DMSCs code, it's a fascinating piece of bit manipulation - thx for expanding my knowledge

##### 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
##### 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!

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

##### Share on other sites

I can't imagine how I can get my code down to 10 lines without some sort of magic.  I might have to try a different category or language!!!

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

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.