Uploaded Facebook videos not playing sound (but do in preview).

I thought I’d share the solution to a puzzling issue I encountered recently with videos uploaded to Facebook. A recorded video (screen capture) had audio that played fine in my local .mov file, and played fine in the Facebook video preview, but once published, it was silent. No sound.

I tried multiple uploads and several videos, and they all did the same thing. Yet, earlier videos recorded with the same screen capture software, the same way (or so I thought) played audio just fine.

It turns out, Facebook does not support multiple tracks of audio in video files. It uses the first set of audio. I’m my case, the change was using a USB microphone to record my narration instead of the built in laptop mic. The capture software was placing the app audio (built in sound from the computer) on the first set of stereo tracks, and then my USB microphone on the second set. Facebook does not honor any tracks beyond the first set.

Had what I was recording had any app audio, I might have noticed this … “hey, my voice is gone but the beeps are still there.”

But my demo was silent, and it took some web searching to figure this out.

Initially, I got it working simply by taking my captured .mov file and importing it into Final Cut Pro X and then exporting it from there. FCP mixes the multiple audio tracks down to stereo for me, per the output file format.

But, a much easier solution (since I was not using audio on the first track) was to use a utility that would just delete the first unused audio track.

My screen capture software does have an option on how it prioritizes audio recording, so there may be an easy fix I can make there.

I thought I’d post this here in case someone else stumbles upon it.

Color BASIC Attract Screen – part 1

See also: part 1, part 2, part 3, part 4, unrelated, part 5 and part 6.

Inspired by some of the title screens on early TRS-80 Color Computer games, tonight I wrote this:

10 ' ATTRACT.BAS
20 A=1024:B=A+23:C=1535:D=C-23:Z=143
30 AD=1:BD=1:CD=-1:DD=-1
40 CLS 0:PRINT @268,"ATTRACT!";
50 POKE A,Z:POKE B,Z:POKE C,Z:POKE D,Z
60 Z=Z+16:IF Z>255 THEN Z=143
70 A=A+AD
80 IF A=1055 THEN AD=32
90 IF A=1535 THEN AD=-1
100 IF A=1504 THEN AD=-32
110 IF A=1024 THEN AD=1
120 ' 
130 B=B+BD
140 IF B=1055 THEN BD=32
150 IF B=1535 THEN BD=-1
160 IF B=1504 THEN BD=-32
170 IF B=1024 THEN BD=1
180 ' 
190 C=C+CD
200 IF C=1055 THEN CD=32
210 IF C=1535 THEN CD=-1
220 IF C=1504 THEN CD=-32
230 IF C=1024 THEN CD=1
240 ' 
250 D=D+DD
260 IF D=1055 THEN DD=32
270 IF D=1535 THEN DD=-1
280 IF D=1504 THEN DD=-32
290 IF D=1024 THEN DD=1
300 GOTO 50

It produces color changing blocks that chase around the screen:

It works by assigning screen POKE memory locations to the four moving blocks. A (1024) is the top left corner, and C (1535) is the bottom right. I then made B halfway between A and C, and D halfway between C and A. See? (I initially started with them in each of the four corners, but since the screen is 32 wide and 16 tall, the pattern did not look very good.)

I assign Z as the graphical block I will be POKEing on to the screen, using 143 (the first solid color block).

20 A=1024:B=A+23:C=1535:D=C-23:Z=143

I then assign four directional (delta) variables for each position — AD is the direction A should move (1 to add one and move it right, -1 to subtract one and move it left, 32 to move it down, or -32 to move it up). A and B are not he top row so they start with deltas of 1 (right). C and D are on the bottom row, so they start with deltas of -1 (left).

30 AD=1:BD=1:CD=-1:DD=-1

I clear the screen to black and print a message in the center of the screen.

40 CLS 0:PRINT @268,"ATTRACT!";

Next, I use POKE to place the graphic block (Z) on to locations A, B, C and D.

50 POKE A,Z:POKE B,Z:POKE C,Z:POKE D,Z

To change the color to the next color block, I add 16 to Z. If it’s larger than 255, I reset it back to the 143 value of the first block. (Solid blocks are 16 apart in the character set).

60 Z=Z+16:IF Z>255 THEN Z=143

Then I just do A=A+AD to get the new position (and the same for B, C and D), then check to see if the new location is one of the four corners, and adjust the delta (movement) variable accordingly.

70 A=A+AD
80 IF A=1055 THEN AD=32
90 IF A=1535 THEN AD=-1
100 IF A=1504 THEN AD=-32
110 IF A=1024 THEN AD=1

This is duplicated for B, C and D, then back to the top to do it all over…

120 ' 
130 B=B+BD
140 IF B=1055 THEN BD=32
150 IF B=1535 THEN BD=-1
160 IF B=1504 THEN BD=-32
170 IF B=1024 THEN BD=1
180 ' 
190 C=C+CD
200 IF C=1055 THEN CD=32
210 IF C=1535 THEN CD=-1
220 IF C=1504 THEN CD=-32
230 IF C=1024 THEN CD=1
240 ' 
250 D=D+DD
260 IF D=1055 THEN DD=32
270 IF D=1535 THEN DD=-1
280 IF D=1504 THEN DD=-32
290 IF D=1024 THEN DD=1
300 GOTO 50

It works!

But it seems to go very, very slowly.

And it’s quite large.

I wonder if you might want to try to make the smallest version that does the same thing (even if it’s slower), and the fastest version (even if it’s larger).

Some Size-Reducing Ideas

For example, to make is small, perhaps using a multidimensional array of POKE locations, like DIM L(3) (it is base zero, so 0-3 would be the elements). That would let all the positions be POKEd in a loop like:

L(0)=1024:L(1)=1024+23:L(2)=1535:L(3)=1535-23
FOR I=0 TO 3:POKE L(I),Z:NEXT

For movement, there could be a location delta array like DIM LD(3) that could have the direction each location is meant to be heading.

LD(0)=1:LD(1)=1:LD(2)=-1:LD(3)=-1

To move each location, code like this could be used:

FOR I=0 TO 3:L(I)=L(I)+LD(I):NEXT

Then, perhaps the screen corners could be in an array, such as DIM C(3), and another corresponding array of delta directions could be used like DIM D(3) set up like this:

CL(0)=1024:CD(0)=1
CL(1)=1055:CD(1)=32
CL(2)=1535:CD(2)=-1
CL(3)=1504:CD(3)=-32

Then, you could check for each block being in a corner and adjust it’s delta using the array as a lookup table:

FOR L=0 TO 3 ' Check each Location
   FOR C=0 TO 3 ' Check each Corner
      IF L(L)=CL(C) THEN LD(L)=CD(L)
   NEXT
NEXT

And instead of hard-coding all these values, maybe they could be read in via READ/DATA statements.

That might make it smaller, but probably slower.

I’ll share three iterations of this program, each one making it smaller than the previous. Then, if we aren’t bored by then, we can look at ways to make it faster.

As always, leave your thoughts in the comments. I bet you know a better way to do this.

Until next time…

Revisiting 10 PRINT RACER

Awhile back I ported 8-Bit Show and Tell‘s “10 PRINT RACER” from Commodore PET to CoCo. I tried to make it a literal port, keeping the code as close as I could to the original. I did, however, mention a few things that could make it faster, taking advantage of things like Extended Color BASIC’s hex values (&H2 is faster to parse than 2, for instance).

The other day, MiaM left a comment on the original article:

It might be faster to use A=ASC(INKEY$) and IF A=4 instead of IF A$=CHR$(4)

– MiaM

Intriguing. The original Commodore version, the direction was read by using GET A$, and I simply converted that over to A$=INKEY$ for Color BASIC. Here is a look at Robin’s Commodore PET original:

1 REM 10 PRINT RACER: 8-BIT SHOW & TELL
5 R$="":PRINT"{CLR}INIT:";:FORX=1TO75:M$=CHR$(205.5+RND(.)):R$=R$+M$:PRINTM$;:NEXT
10 PRINT"{CLR}":C=20:R=13:W=15:D=0:S=32768
20 L=0:FORZ=0TO1STEP0:X=RND(.)*10
30 IFX<4THENR=R-1:IFR<1THENR=1
40 IFX>6THENR=R+1:IFR+W>37THENR=37-W
50 RN=RND(.)*35+1:PRINTMID$(R$,RN,R);SPC(W);MID$(R$,RN,39-R-W)
60 D=D+1:L=L+1:IFL>49THENL=0:W=W-1:IFW<3THENW=3
70 IFD<25THENNEXT
75 GETA$:IFA$="4"THENC=C-1
80 IFA$="6"THENC=C+1
90 P=PEEK(S+C):IFP<>32THEN200
100 POKES+C,42:NEXT
200 PRINTSPC(17)"CRASH!":IFD>HTHENH=D
205 PRINT,"SCORE:"D"  HIGH:"H
210 FORX=1TO2000:NEXT:POKE158,0
220 GETA$:IFA$=""THEN220
230 GOTO10

And here is my Color BASIC conversion:

0 ' 10 PRINT RACER
1 ' BY WWW.8BITSHOWANDTELL.COM
2 '
3 ' PORTED FROM PET TO COCO
4 ' BY SUBETHASOFTWARE.COM
5 R$="":CLS:PRINT"INIT:";:FORX=1TO75:M$=CHR$(47+45*(RND(2)-1)):R$=R$+M$:PRINTM$;:NEXT
6 S$=STRING$(32," ")
10 CLS:C=16:R=10:W=12:D=0:S=1024
20 L=0:FORZ=0TO1STEP0:X=RND(.)*10
30 IFX<4THENR=R-1:IFR<1THENR=1
40 IFX>5THENR=R+1:IFR+W>29THENR=29-W
50 RN=RND(.)*28+1:PRINTMID$(R$,RN,R);MID$(S$,1,W);MID$(R$,RN,31-R-W)
60 D=D+1:L=L+1:IFL>49THENL=0:W=W-1:IFW<3THENW=3
70 IFD<16THENNEXT
75 A$=INKEY$:IFA$=CHR$(8)THENC=C-1
80 IFA$=CHR$(9)THENC=C+1
90 P=PEEK(S+C):IFP<>96THEN200
100 POKES+C,106:NEXT
200 PRINTTAB(13)"CRASH!":IFD>H THENH=D
205 PRINTTAB(6)"SCORE:"D"  HIGH:"H
210 FORX=1TO2000:NEXT:A$=INKEY$
220 A$=INKEY$:IFA$=""THEN220
230 GOTO10

The block of code MiaM refers to is this:

75 GETA$:IFA$="4"THENC=C-1
80 IFA$="6"THENC=C+1

75 A$=INKEY$:IFA$=CHR$(8)THENC=C-1
80 IFA$=CHR$(9)THENC=C+1

On the Commodore PET, without arrow keys, it used “4” and “6” on the numeric keypad for Left and Right. On the CoCo, I changed that to the Left Arrow key and the Right Arrow key.

The Commodore PET has much less work to do looking for A$=”4″ versus A$=CHR$(8) not he CoCo (due to all the parsing). I could have made the CoCo use letter keys like “A” for left and “S” for right to get similar performance.

But what MiaM suggests may be faster. Instead of comparing strings like A$=CHR$(8), the suggestion is to use BASIC’s ASC() keyword to return the numeric value of the character, then compare a numeric value rather than a string compare.

Which is faster? A one character string compare, or ASC() and a number compare?

Let’s find out.

Comparing a String to a String

For this, I dug out my old BENCH.BAS benchmarking code and inserted the first method I wanted to test — the way the Commodore PET did it:

5 DIM TE,TM,B,A,TT
10 FORA=0TO3:TIMER=0:TM=TIMER
20 FORB=0TO1000
30 A$=INKEY$:IF A$="4" THEN REM

70 NEXT
80 TE=TIMER-TM:PRINTA,TE
90 TT=TT+TE:NEXT:PRINTTT/A:END

Comparing A$ to a quoted value in this loop produces 515.

Comparing a String to a CHR$

My conversion changed this to comparing to a CHR$(8) value, like this:

0 REM ascvsstringcompare.BAS
5 DIM TE,TM,B,A,TT
10 FORA=0TO3:TIMER=0:TM=TIMER
20 FORB=0TO1000
30 A$=INKEY$:IF A$="4" THEN REM
30 A$=INKEY$:IF A$=CHR$(8) THEN REM

70 NEXT
80 TE=TIMER-TM:PRINTA,TE
90 TT=TT+TE:NEXT:PRINTTT/A:END

This produces a slower 628. No surprise, due to having to parse CHR$() and the number. I could easily speed up the CoCo port by using quoted characters like “A” for Left and “S” for Right.

But I really wanted to use the arrow keys.

ASC and you shall receive…

The new suggestion is to use ASC. ASC will convert a character to its ASCII value (or PETASCII on a Commodore, I would suppose). For example:

PRINT ASC("A")
65

The cool suggestion was to try using INKEY$ as the parameter inside of ASC(), and skipping the use of a variable entirely. Unfortunately, when I tried it, I received:

?FC ERROR

Function Call error. Because, if no key is pressed, INKEY$ returns nothing, which I suppose would be like trying to do:

PRINT ASC("")

We have been able to use INKEY$ directly in other functions, such as INSTR (looking up a character inside a string), and that works even when passing in “”:

PRINT INSTR("","ABCDE")
0

But ASC() won’t work without a character, at least not in Color BASIC. And, even if we used A$=INKEY$, we can’t pass A$ in to ASC() if it is empty (no key pressed) which means we’d need an extra check like:

30 A$=INKEY$:IF A$<>"" THEN IF ASC(A$)=4 THEN ..

The more parsing, the slower. This produced 539, which isn’t as slow as I expected. It’s slower than doing IF A$=”4″ but faster than IF A$=CHR$(8). Thus, it would be faster in my CoCo port than my original.

This did give me another thing to try. ASC() allows you to pass in a string that contains more than one character, but it only acts upon the first letter. You can do this:

PRINT ASC("ALLEN TRIED THIS")
65

This means I could always pad the return of INKEY$ with another character so it would either be whatever keys he user pressed, or my other character if nothing was pressed. Like this:

30 IF ASC(INKEY$+".")=8 THEN REM

If no key has been pressed, this would try to parse “”+”.”, and give me the ASCII of “.”.

If a key had been pressed, this would parse that character (like “4.” if I pressed a 4).

As I learned when I first stated my benchmarking BASIC series, string manipulation is slow. Very slow. So I expect this to be very slow.

To my surprise, it returns 520! Just a smidge slower than the original IF A$=”4″ string compare! I’m actually quite surprised.

Now, in the actual 10 PRINT RACER game, which is doing lots of string manipulations to generate the game maze, this could end up being much slower if it had to move around other larger strings. But, still worth a shot.

Thank you, MiaM! Neat idea, even if Color BASIC wouldn’t let me do it the cool way you suggested.

Until next time…

Bonus

Numbers verses string compares:

30 IF Z=4 THEN REM

That gives me 350. Even though decimal values are much slower to parse than HEX values, they are still faster than strings.

But, in pure Color BASIC, there is no way to get input from a keypress to a number other than ASC. BUT, you could PEEK some BASIC RAM value that is the key being held down, and do it that way (which is something I have discussed earlier).

Any more ideas?

10 PRINT big maze in Color BASIC – part 4

See also: part 1, part 2, part 3 and part 4.

My “big maze” program printed 2×2 character blocks along the bottom of the screen until it got to the bottom right of the screen, then the screen will scroll (and an extra PRINT is added to add a second line) and the process resets and repeats.

After William Astle provided some optimizations, it dawns on me that there was another thing we could try. Here is the code in question (removing unneeded lines and adjusting the GOTO as appropriate):

70 P=448
100 P=P+2:IF P>479 THEN PRINT:GOTO 70
110 GOTO 100

Then William suggested changing the logic it as follows:

70 PRINT:P=448
...
100 P=P+2:IF P>479 THEN 70
110 GOTO 100

That was a very subtle change that could double (or more, or less) the speed just by not needing to parse over “PRINT:GOTO 70” every time P was NOT greater than 479 (which is most of the time in that loop).

This made me think that perhaps instead of checking for greater than 479 we could adjust the logic and check for less than 480. Something like this, perhaps:

70 PRINT:P=448
...
100 P=P+2:IF P<480 THEN 100
110 GOTO 70

There’s really no reason for this to be any different speed, is there? GOTO (“THEN”) 100 still has to start at the top and move forward, the same as GOTO (“THEN”) 70 would.

But, in the first case, it quickly skips “THEN 70” to hit the “GOTO 100” below, every time the value is not greater than 479. That

In the second, every time the value is LESS than 480 it returns to 100 (go to top of program and search forward).

Should it matter?

Here is the logic isolated.

5 TIMER=0
10 PRINT:P=0
20 P=P+1:IF P<1001 THEN 20
30 GOTO 50
50 PRINT TIMER

And here is the other version:

5 TIMER=0
10 PRINT:P=0
20 P=P+1:IF P>1000 THEN 50
30 GOTO 20
50 PRINT TIMER

I have adjusted it to reset the TIMER at the start, and count from 0 to 1000. In each case, instead of repeating forever, it ends, printing the TIMER.

The first version looks odd because in the real version, line 30 would be “GOTO 10” to reset P and continue.

The second version would have line 20 end with “THEN 10” to reset and continue.

I just wanted to make them as close as possible.

Which one is faster?

Until next time…

10 PRINT big maze in Color BASIC – part 3

See also: part 1, part 2, part 3 and part 4.

When we last left off, it had been so long since I did any BASIC programming that I found myself wondering why these two sections of BASIC did not perform as I expected:

0 'bigmazebench.bas
100 P=0:TIMER=0:A=0
110 P=0
120 P=P+2:IF P>479 THEN PRINT:GOTO 110
120 A=A+1:IF A >1000 THEN 150
140 GOTO 120
150 PRINT TIMER

200 P=0:TIMER=0:A=0
210 PRINT:P=0
220 P=P+2:IF P>479 THEN 210
230 A=A+1:IF A>1000 THEN 250
240 GOTO 220
250 PRINT TIMER

William Astle once again saw the obvious (just not obvious to me at the time)…

If you have both versions in the same program, the “backwards” jumps will be slower the later in the program they are because they have to do a sequential scan of the program from the beginning to find the correct line number. If you have been running them in the same program, try separating them and running them independently.

– William Astle

Well, duh. Of course. When the block of code starting at line 200 runs, the GOTO 220 has to start at the top of the program and seek past every line to find 220. Much slower compared to how few lines the GOTO 120 has to. Normally my benchmark program is inside a FOR/NEXT loop so there is no line seeking and it behaves the same speed regardless of line number location…

So let’s try them one at a time. I loaded the program and deleted the line 0 comment, and lines 200 and up (DEL 0 and DEL 200-):

100 P=0:TIMER=0:A=0
110 P=0
120 P=P+2:IF P>479 THEN PRINT:GOTO 110
120 A=A+1:IF A >1000 THEN 150
140 GOTO 120
150 PRINT TIMER

This gives me 762.

Then, loading it again, and deleting everything up to 200 (“DEL -199”):

200 P=0:TIMER=0:A=0
210 PRINT:P=0
220 P=P+2:IF P>479 THEN 210
230 A=A+1:IF A>1000 THEN 250
240 GOTO 220
250 PRINT TIMER

That gives me 1394!

Yep, William’s suggestion of moving the PRINT to the destination line, instead of using “THEN PRINT:GOTO xxx” almost doubled the speed it takes to run through that code.

Nicely done, William.

Until next time…

10 PRINT big maze in Color BASIC – part 2

See also: part 1, part 2, part 3 and part 4.

Previously, I presented this Color BASIC program:

0 ' BIGMAZE.BAS
10 C=2
20 B$=CHR$(128)
30 L$=CHR$(128+16*C+9)
40 R$=CHR$(128+16*C+6)
50 M$(0,0)=B$+R$:M$(0,1)=R$+B$
60 M$(1,0)=L$+B$:M$(1,1)=B$+L$
70 P=512-32*2
80 M=RND(2)-1
90 PRINT@P,M$(M,0);:PRINT@P+32,M$(M,1);
100 P=P+2:IF P>479 THEN PRINT:GOTO 70
110 GOTO 80

Running it produces this:

4×4 Maze

And I ended with “Make it smaller. Make it faster.”

William Astle commented:

Welp, everything up to line 60 can be mashed into a single line. Since it’s all setup and none of it is performance critical, you can dispense with the variables and just set the M$ array directly. More typing, but it keeps the variable table smaller. Or define P right at the start so it’s the first variable in the table which would give you a speedup all on its own since the lookups to find P will be faster.

I suspect that if you put the PRINT statement from line 100 at, say, the start of line 70 and have “THEN 70” instead of “THEN PRINT:GOTO 70”, you might get a bit of a performance gain there, especially in the false case where that gives a handful fewer bytes to skip over.

There might be some sort of trick involving FOR/NEXT that can be used to improve the main loop but I think the overhead of setting up a FOR loop will be more than the saving in this case, especially if the setup lines are combined into a single program line.

On a side note, and this won’t improve the speed any, you could put a DIM M(1,1) at the start to avoid the implied DIM M(10,10). That saves a bit of memory, though I don’t think that’s even an issue for this program even on a 4K machine. But it is 585 bytes nevertheless.

– William Astle

Let’s start with the “everything up to line 60” part, which gives us this:

10 M$(0,0)=CHR$(128)+CHR$(166):M$(0,1)=CHR$(166)+CHR$(128):M$(1,0)=CHR$(169)+CHR$(128):M$(1,1)=CHR$(128)+CHR$(169)

If I compare that to the original, it’s about a few less characters to type:

10 C=2:B$=CHR$(128):L$=CHR$(128+16*C+9):R$=CHR$(128+16*C+6):M$(0,0)=B$+R$:M$(0,1)=R$+B$:M$(1,0)=L$+B$:M$(1,1)=B$+L$

It loses the ability to change the color of the maze (easily), but it saves three string variables (B$ for blank block, R$ for right block, and L$ for left block) and one numeric variable (C for color). Definitely lower RAM use, and I am sure it is code-space too since you can’t tokenize “128+16*C+6” (10 bytes) which is replaced by “166”.

Combining the rest of the lines, where possible, and moving the PRINT (so line 100 has a bit less to parse through to get to the end of that line when P>479 is not true) results in:

0 ' BIGMAZE2.BAS - William Astle
10 M$(0,0)=CHR$(128)+CHR$(166):M$(0,1)=CHR$(166)+CHR$(128):M$(1,0)=CHR$(169)+CHR$(128):M$(1,1)=CHR$(128)+CHR$(169)
70 PRINT:P=448
80 M=RND(2)-1:PRINT@P,M$(M,0);:PRINT@P+32,M$(M,1);:P=P+2:IFP>479THEN70
110 GOTO80

On my simulated CoCo, removing the REM statements, then loading the original version and doing “? MEM” showed 8256. Doing the same to the second version shows 8307 — saving 51 bytes of program space. I did not measure what the saving in string and variable memory would be, but that would be even more. Great win.

Since the difference was mostly in the setup of the variables, they should run at the same speed — or will they? Let’s quickly test William’s suggestion of moving the PRINT so the IF statement doesn’t have to parse the end of the line:

0 'bigmazebench.bas
100 P=0:TIMER=0:A=0
110 P=0
120 P=P+2:IF P>479 THEN PRINT:GOTO 110
120 A=A+1:IF A >1000 THEN 150
140 GOTO 120
150 PRINT TIMER

200 P=0:TIMER=0:A=0
210 PRINT:P=0
220 P=P+2:IF P>479 THEN 210
230 A=A+1:IF A>1000 THEN 250
240 GOTO 220
250 PRINT TIMER

Not very elegant, but it should do the job. Since I could not easily use a FOR/NEXT loop for the counter, I used A and a check in line 130 or 230 to exit the test.

This prints 771 for the first one, and 1414 for the second one.

This is not what I would have expected. I must be doing something wrong, because I agree with William that…

IF P>479 THEN PRINT:GOTO 210

…should be slower every time P is NOT greater than 479, compared to:

IF P>479 THEN 210

In the first example, each time P is not greater than 479, BASIC should still have to skip everything past then THEN looking for either ELSE or the end of the line. It should be scanning past a PRINT and GOTO token then the number 220.

In the second example, it should only have to skip the number 210.

I think I did something wrong.

What am I missing?

To be continued…

10 PRINT big maze in Color BASIC – part 1

See also: part 1, part 2, part 3 and part 4.

Awhile back, I discussed the famous Commodore 10 PRINT one-line program, inspired by a YouTube video from 8-Bit Show and Tell.

Commodore PET running the 10 PRINT program.

Although most computers could do the same program in BASIC, unless your system had those wonderful diagonal graphics characters, the result could be a bit lacking.

Scrolling maze… Sorta.

On the CoCo, using the 2×2 block graphics characters was not an improvement, either.

But perhaps if you used a 4×4 block it might look more like a maze. This allows 16 maze characters across by 8 down (versus a Commodore VIC-20 with 22×23).

4×4 Maze

Well, it works, but takes up much more than one line. How small can you make it? Here is my version:

0 ' BIGMAZE.BAS
10 C=2
20 B$=CHR$(128)
30 L$=CHR$(128+16*C+9)
40 R$=CHR$(128+16*C+6)
50 M$(0,0)=B$+R$:M$(0,1)=R$+B$
60 M$(1,0)=L$+B$:M$(1,1)=B$+L$
70 P=512-32*2
80 M=RND(2)-1
90 PRINT@P,M$(M,0);:PRINT@P+32,M$(M,1);
100 P=P+2:IF P>479 THEN PRINT:GOTO 70
110 GOTO 80

Make it smaller. Make it faster. Share your work. And someone tell Jim Gerrie since he probably has already done this…

Until next time…

Odd or Even in Color BASIC?

In my 3X+1 post, I needed to check if a value was odd or even. I did so by using “AND 1” which would test the least significant bit. This works, and is fast, but is limited to values 32767 or lower (15 bits).

Comments from William Astle, RogelioP and John offered corrections and updates to my code. I decided to benchmark a few different methods for detecting if a value was odd or even, and here is what I came up with.

0 REM 3x+1 Benchmarking

5 'GOTO 300

100 ' 0-32767 ONLY
110 TIMER=0
120 FOR A=1 TO 1000
130 IF X AND 1 THEN REM
140 NEXT:PRINT TIMER

200 ' ALL RANGES?
210 TIMER=0
220 FOR A=1 TO 1000
230 IF INT(X/2)=X/2 THEN REM
240 NEXT:PRINT TIMER

300 ' ROGELIO P
310 TIMER=0
320 FOR A=1 TO 1000
330 IF INT(X/2)*2=X THEN REM
340 NEXT:PRINT TIMER

400 ' WILLIAM ASTLE
405 T=0:H=0.5
410 TIMER=0
420 FOR A=1 TO 1000
430 T=X*H:IF T=INT(T) THEN REM
440 NEXT:PRINT TIMER

500 ' DIVIDE TEST
505 T=0:H=2
510 TIMER=0
520 FOR A=1 TO 1000
530 T=X/H:IF T=INT(T) THEN REM
540 NEXT:PRINT TIMER

When I run this program in Xroar on my Raspberry Pi 400, I get:

313
508
506
485
485

As expected, AND is the fastest, so use this if you know your values will be 32767 or lower.

Using INT(X/2)=X/2 was a fraction slower as INT(X/2)*2=X, which I guess makes sense since both do an INT and two math functions.

William’s suggestion of multiplying by .5 instead of dividing by two rang a bell. I believe he (or someone) pointed this out to me a few years ago when I was doing similar benchmarks. A big speed up comes just from putting the value in a variable, but I was surprised to see that dividing by a variable of 2 was the same speed as multiplying by a variable of .5.

What ideas do you have? Anything with math (“/2”) can be sped up by using a variable (“/H”), so there are some improvements just from that. Using HEX values (“&H2”) instead of decimal is also faster, as is removing extra spaces.

But are there better approaches we can use?

Thoughts appreciated.

3X+1 in C#

For my day job, I do embedded C programming for PIC24 compilers and some Windows C programming in something called LabWindows. Lately, I’ve been touching some C# stuff, so I decided to revisit last night’s 3X+1 program by converting it to C#.

You can compile and run it online here: https://www.onlinegdb.com/online_csharp_compiler

// 3X+1

using System;
					
public class Program
{
	public static void Main()
	{
		while (true)
		{
			Int32 x = 0;

			Console.WriteLine();
			Console.Write("STARTING NUMBER? ");
			x = Int32.Parse(Console.ReadLine());
			
			while (true)
			{
				Console.Write(x);
				Console.Write(" ");
				
				if (x == 1) break;
				
				if ((x & 1) == 1) // Odd
				{
					x = x * 3 + 1;
				}
				else // Even
				{
					x = x / 2;
				}
			}
		}
	}
}