[Question]
  [
What general tips do you have for golfing in QBasic? I'm looking for ideas that can be applied to code golf problems in general that are at least somewhat specific to QBasic (e.g. "remove comments" is not an answer).
Tips pertaining to the [QB64](https://www.qb64.org/) emulator are also welcome. It has some extra features that aren't in Microsoft QBasic.
  
[Answer]
# Know your looping constructs
QBasic has several looping constructs: `FOR ... NEXT`, `WHILE ... WEND`, and `DO ... LOOP`. You can also use `GOTO` or (in some situations) `RUN` to loop.
* `FOR ... NEXT` is pretty good at what it does. Unlike in Python, it's almost always shorter than the equivalent `WHILE` or `GOTO` loop, even when it gets a little fancier:
```
FOR i=1TO 19STEP 2:?i:NEXT
i=1:WHILE i<20:?i:i=i+2:WEND
i=1:9?i:i=i+2:IF i<20GOTO 9
```
Note that you don't need to repeat the variable name after `NEXT`, and you can eliminate space between numbers and most following keywords.
* `WHILE ... WEND` is good for when you have a loop that might need to execute 0 times. But if you know the loop will execute at least once, `GOTO` might be one byte shorter:
```
WHILE n>1:n=n\2:WEND
1n=n\2:IF n>1GOTO 1
```
* I only use `DO ... LOOP` for infinite loops (except where `RUN` can be used instead). While it costs the same number of characters as an unconditional `GOTO`, it's a little more intuitive to read. (Note that "infinite loop" can include loops that you break out of using a `GOTO`.) The `DO WHILE`/`DO UNTIL`/`LOOP WHILE`/`LOOP UNTIL` syntax is too verbose; you're better off using `WHILE` or `GOTO` as appropriate.
* `GOTO` is, as mentioned above, the shortest general way to write a do/while loop. Use single-digit line numbers instead of labels. Note that when a `GOTO` is the only thing in the `THEN` part of an `IF` statement, there are two equally terse shortcut syntaxes available:
```
IF x>y GOTO 1
IF x>y THEN 1
```
`GOTO` can also be used to create [more complicated control flows](https://codegolf.stackexchange.com/a/107657/16766). The naysayers refer to this as "spaghetti code," but this is code golf: unreadability is almost a virtue! `GOTO` pride!
* `RUN` is useful when you need to jump to a fixed place in the program and you don't need to keep any of the variables' values. `RUN` by itself will restart the program from the top; with a label or line number, it will restart at that line. I've mainly used it to [create stateless infinite loops](https://codegolf.stackexchange.com/a/47398/16766).
[Answer]
# Divisibility testing
In programs that require you to test whether one integer is divisible by another, the obvious way is to use `MOD`:
```
x MOD 3=0
```
But a shorter way is to use integer division:
```
x\3=x/3
```
That is, `x` int-div `3` equals `x` float-div `3`.
Note that both of these approaches will return `0` for falsey and `-1` for truthy, so you may need to negate the result, or subtract it instead of adding.
---
If you need the opposite condition (i.e. `x` is *not* divisible by `3`), the obvious approach is to use the not-equals operator:
```
x\3<>x/3
```
But if `x` is guaranteed to be nonnegative, we can save a byte. Integer division truncates the result, so it will always be less than or equal to float division. Therefore, we can write the condition as:
```
x\3<x/3
```
Similarly, if `x` is guaranteed to be negative, truncation *increases* the result, and we can write `x\3>x/3`. If you don't know the sign of `x`, you'll have to stick to `<>`.
[Answer]
# Scanner abuse
As in a lot of languages, knowing which characters can and can't be removed is important.
* Any space next to a symbol can be removed: `IF""=a$THEN?0`
* Space can usually be removed between a digit and a letter occurring *in that order*: `FOR i=1TO 10STEP 2`. There are some differences between QBasic 1.1 (available at [archive.org](http://archive.org/details/msdos_qbasic_megapack)) and [QB64](http://qb64.net):
	+ QBasic 1.1 allows removal of space between any digit and a following letter. Furthermore, in print statements, it will infer a semicolon between consecutive values: `?123x` becomes `PRINT 123; x`. The exceptions to the above are sequences like `1e2` and `1d+3`, which are treated as scientific notation and expanded to `100!` and `1000#` (single- and double-precision, respectively).
	+ QB64 is generally the same, but digits can't be followed by `d`, `e`, or `f` at all unless they are part of a well-formed scientific notation literal. (For example, you can't omit the space after the line number in `1 FOR` or `9 END`, like you can in QBasic proper.) It only infers semicolons in print statements if one of the expressions is a string literal: `?123"abc"` works, but not `?TAB(5)123` or `?123x`.
* Speaking of semicolons, QBasic 1.1 adds a trailing semicolon to a `PRINT` statement that ends with a call to `TAB` or `SPC`. (QB64 does not.)
* `0` can be omitted before or after the decimal point (`.1` or `1.`), but not both (`.`).
* `ENDIF` is equivalent to `END IF`.
* The closing double quote of a string can be omitted at the end of a line.
[Answer]
# Use shortcuts for `PRINT` and `REM`
You can use `?` instead of `PRINT`, and `'` instead of `REM` (comment).
`'` might also come useful when polygloting with languages that support `'` as a part of char or string syntax.
[Answer]
# Know your input methods
QBasic has several ways to get user keyboard input: `INPUT`, `LINE INPUT`, `INPUT$`, and `INKEY$`.
* `INPUT` is your standard multipurpose input statement. The program stops what it's doing, displays a cursor, and lets the user type some input, terminated by `Enter`. `INPUT` can read numbers or strings, and it can read multiple values comma-separated. You can specify a string as a prompt, you can go with the default question-mark prompt, and you can even (I just learned this tonight) suppress the prompt altogether. Some sample invocations:
	+ `INPUT x$,y`  
	
	Uses the default `?`  prompt and reads a string and a number, comma-separated.
	+ `INPUT"Name";n$`  
	
	Prompts with `Name?`  and reads a string.
	+ `INPUT"x=",x`  
	
	Prompts with `x=` (no question mark! note the comma in the syntax) and reads a number.
	+ `INPUT;"",s$`  
	
	Suppresses the prompt (using the above comma syntax with an empty prompt string), reads a string, and does not move to the next line when the user hits enter (that's what the semicolon after `INPUT` does). For example, if you `PRINT s$` immediately after this, your screen will look like `User_inputUser_input`.
* One drawback of `INPUT` is that you can't read a string with a comma in it, since `INPUT` uses comma as a field separator. To read a single line of arbitrary (printable ASCII) characters, use `LINE INPUT`. It's got the same syntax options as `INPUT`, except it takes exactly one variable which must be a string variable. The other difference is that `LINE INPUT` does not display a prompt by default; if you want one, you'll have to specify it explicitly.
* `INPUT$(n)` displays no prompt or cursor but simply waits until the user enters `n` characters, and then returns a string containing those characters. Unlike `INPUT` or `LINE INPUT`, the user doesn't need to press `Enter` afterwards, and in fact `Enter` can be one of the characters (it'll give ASCII character 13, known to C-like languages as `\r`). 
Most often, this is useful as `INPUT$(1)`, typically in a loop. `INPUT$` is good in [interactive programs where single keypresses do things](https://codegolf.stackexchange.com/a/147623/16766). Unfortunately, it only works with keys that have ASCII codes; this includes things like `Esc` and `Backspace`, but not the arrow keys, `Insert` and `Delete`, and others.
* Which is where `INKEY$` comes in. It is similar to `INPUT$(1)` in that it returns the results of a single keypress1, but different in that:
	+ `INKEY$` takes no argument.
	+ While `INPUT$(n)` halts execution until the user enters `n` characters, `INKEY$` does not halt execution. If the user is currently pressing a key, `INKEY$` returns a string representing that key; if not, it returns `""`. This means that if you want to use `INKEY$` to get the next keypress, you have to wrap it in a [busy-waiting](https://en.wikipedia.org/wiki/Busy_waiting) loop:2
	
	
	
	```
	k$=""
	WHILE""=k$
	k$=INKEY$
	WEND
	
	```
	+ Both `INPUT$` and `INKEY$` return ASCII characters for keys that correspond to ASCII characters (including control characters like escape, tab, and backspace). However, `INKEY$` can also handle some keys that do not have ASCII codes. For these (saith the help file), "INKEY$ returns a 2-byte string made up of the null character (ASCII 0) and the keyboard scan code."
	
	
	Clear as mud? Here's some examples. If you use the `INKEY$` loop above to capture a keypress of the left arrow key, `k$` will contain the string `"␀K"` (with the `K` representing scan code 75). For the right arrow, it's `"␀M"` (77). Page down is `"␀Q"` (81). F5 is `"␀?"` (63).
	
	
	Still clear as mud? Yeah. It's not the most intuitive thing in the world. The help file has a table of scan codes, but I always just write a little program to print the results of `INKEY$` and press a bunch of keys to find out what the right values are. Once you know which characters correspond to which keys, you can use `RIGHT$(k$,1)` and `LEN(k$)` to distinguish between all the different cases you may encounter.Bottom line? `INKEY$` is weird, but it's the only way to go if your program requires non-blocking input or [needs to use the arrow keys](https://codegolf.stackexchange.com/a/49082/16766).
---
1 Not including `Shift`, `Ctrl`, `Alt`, `PrntScr`, `Caps Lock`, and similar. Those don't count. :^P
2 The `WHILE ... WEND` idiom here is what I learned in my QBasic books. For golfing purposes, however, [a `GOTO` loop is shorter](https://codegolf.stackexchange.com/a/147627/16766).
[Answer]
# Combine `Next` Statements
```
Next:Next:Next
```
May be condensed down to
```
Next k,j,i
```
where the iterators for the `For` loops are `i`,`j`, and `k` - in that order.
For example the below (69 Bytes)
```
Input n,m,o
For i=0To n
For j=0To m
For k=0To o
?i;j;k
Next
Next
Next
```
May be condensed down to 65 Bytes
```
Input n,m,o
For i=0To n
For j=0To m
For k=0To o
?i;j;k
Next k,j,i
```
And as far as how this impacts formatting and indentation, I think the best approach to handling this is left aligning the next statement with the outer most for statement. Eg.
```
Input n,m,o
For i=0To n
    For j=0To m
        For k=0To o
            ?i;j;k
Next k,j,i
```
[Answer]
# `PRINT` (`?`) has some quirks
Numbers are printed with a leading and trailing space.
Printing adds a linebreak. This behaviour can be altered by adding a comma at the end of the statement to insert a tab instead, or a semi-colon to avoid any insertions.
It is not necessary to use `+` or `;` between distinct expressions when printing, eg. `?1"x"s$` prints the number `1`, with spaces on each side, the letter `x` and the contents of `s$`.
```
?"foo"
?"bar"
?10
?"foo",
?"bar"
?"foo"; 
?"bar"
?1CHR$(65)
?1" "CHR$(65)
?"A","B
```
Outputs
```
foo
bar
 10
foo           bar
foobar
 1 A
 1  A
A             B
```
Printing a linebreak can be done with just `?`.
[Answer]
# LOCATE can be really powerful
The `LOCATE` statement allows you to place the cursor anywhere on the screen (within the usual 80x40 character space limits) and print something at that location. [This answer](https://codegolf.stackexchange.com/a/147623/44874) to a challenge really shows this off (and is also combined with a lot of other tips from this topic).
The challenge asks us to output every character a user has pressed in a 16x6 grid. With `LOCATE` this is simply a matter of div and mod over the ASCII code (`a` in this code):
```
LOCATE a\16-1,1+2*(a MOD 16)
```
And then printing the character:
```
?CHR$(a)
```
[Answer]
In QBasic, it is customary to use the `DIM` statement to create variables, giving them a name and a type. However, this isn't mandatory, QBasic can also derive a type by the suffix of the variable's name. Since you can't declare and initialise a variable at the same time, it's often wise to skip the `DIM` in codegolf. Two snippets that are functionally identical\*:
```
DIM a AS STRING: a = "example"
a$ = "example"
```
\* Note that this does create two different variable names.
We can specify the type of the variable by adding `$` to the end of a variable name for strings, `!` for single precision numbers and `%` for doubles. Singles are assumed when no type is specified.
```
a$ = "Definitely a string"
b! = "Error!"
```
Note that this also holds for arrays. Usually, an array is defined as:
```
DIM a(20) AS STRING
```
But arrays also don't need to be `DIM`med:
```
a$(2) = "QBasic 4 FUN!"
```
`a$` is now an array for strings with **11** slots: from index 0 to and including index 10. This is done because QBasic has an option that allows both 0-based and 1-based indexing for arrays. A default array kind of supports both this way.
Remember the twenty-slot array we `DIM`med above? That actually has 21 slots, because the same principle applies to both dimmed and non-dimmed arrays.
[Answer]
# Shortening `IF` statements
`IF` statements are rather expensive, and golfing them down can save a lot of bytes.
Consider the following (adapted from an [answer](https://codegolf.stackexchange.com/a/166106) by Erik the Outgolfer):
```
IF RND<.5THEN
x=x-1
a(i)=1
ELSE
y=y-1
a(i)=0
ENDIF
```
The first thing we can do is save the `ENDIF` by using a single-line `IF` statement:
```
IF RND<.5THEN x=x-1:a(i)=1ELSE y=y-1:a(i)=0
```
This works as long as you don't try to put it on the same line as anything else. In particular, if you have nested `IF` statements, only the innermost one can be one-lined.
But in this case, we can eliminate the `IF` entirely using math. Consider what we actually want:
* If `RND<.5` is true (`-1`), we want:
	+ `x` to decrease by 1
	+ `y` to stay the same
	+ `a(i)` to become 1
* Otherwise, if `RND<.5` is false (`0`), we want:
	+ `x` to stay the same
	+ `y` to decrease by 1
	+ `a(i)` to become 0
Now if we save the result of the conditional in a variable (`r=RND<.5`), we can calculate the new values of `x`, `y`, and `a(i)`:
* When `r` is `-1`, `x=x-1`; when `r` is `0`, `x=x+0`.
* When `r` is `-1`, `y=y+0`; when `r` is `0`, `y=y-1`.
* When `r` is `-1`, `a(i)=1`; when `r` is `0`, `a(i)=0`.
So our final code looks like:
```
r=RND<.5
x=x+r
y=y-1-r
a(i)=-r
```
saving a whopping 20 bytes (40%) over the original version.
---
The math approach can be applied surprisingly often, but when there's a difference in logic between the two cases (e.g. when you need to input something in one case but not in the other), you will still need to use `IF`.
[Answer]
# Sometimes, you should avoid arrays
Arrays in QBasic, when instantiated without `DIM` have only 11 slots. If a challenge requires more than 11 slots (or N slots, where N can be bigger than 11), you should `DIM` the array. Also, let's assume we want to populate this array with data:
```
DIM a$(12)
a$(0) = "Value 1"
a$(1) = "Value 2"
...
```
Even golfed, this can take up a lot of space. On such occasions, it might be cheaper in bytes to do this:
```
a$ = "value 1value 2"
```
Here, we place everything in 1 concatenated string. Later, we access it like so:
```
?MID$(a$,i*7,7)
```
For this approach, it is important that all values are of equal length. Take the longest value and pad out all the others:
```
a$="one  two  threefour "
```
You don't need to pad the last value, and you can even skip the closing quotes! If the challenge specifies that white-space is not allowed in the answer, use `RTRIM$()` to fix that.
You can see this technique in action [here](https://codegolf.stackexchange.com/a/166554/44874).
[Answer]
# `WRITE` may be useful in place of `PRINT`
`PRINT` is usually the way you'll want to do output, since it's pretty flexible and has the `?` shortcut. However, the `WRITE` command can save you bytes in specific situations:
* When outputting a string, `WRITE` wraps it in double quotes (`"`). If you need output with double quotes, `WRITE s$` is much shorter than `?CHR$(34);s$;CHR$(34)`. See, for example, [the shortest known QBasic quine](https://codegolf.stackexchange.com/a/47119/16766).
* When outputting a number, `WRITE` does not add spaces before and after it like `PRINT` does. `WRITE n` is much shorter than `?MID$(STR$(n),2)`. See, for example, [FizzBuzz in QB64](https://codegolf.stackexchange.com/a/58834/16766).
* When outputting multiple values, `WRITE` separates them with commas: `WRITE 123,"abc"` outputs `123,"abc"`. I can't think of a scenario where this would be useful, but that doesn't mean there isn't one.
Limitations of `WRITE`:
* There is no way to output multiple values without a separator like with `PRINT a;b`.
* There is no way to suppress the newline at the end of output. (You may be able to work around this with `LOCATE`, but that costs a lot of bytes.)
[Answer]
# Sometimes, QBasic mangles inputs to functions. Abuse that!
There's a couple of functions that work on characters instead of strings, but there isn't a `char` datatype in QBasic, there is only the `string ($)` type. Take for instance the `ASC()` function, which returns the ASCII keycode for a character. If we would enter
```
PRINT ASC("lala")
```
only the first `l` would be considered by QBasic. This way, we don't have to bother with cutting a string down to length 1.
Another example comes from [this question](https://codegolf.stackexchange.com/questions/125133/is-this-number-a-repdigit/) where the `STRING$()` function is used in one of the answers.
> 
> The STRING$ function takes two arguments, a number n and a string s$, and constructs a string consisting of n copies of the first character of s$
> 
> 
> @DLosc, [here](https://codegolf.stackexchange.com/questions/125133/is-this-number-a-repdigit/167102)
> 
> 
> 
Note that QBasic, when offered a multi-char string and needing only one char, automatically takes the first char and ignores the rest.
[Answer]
# `Integer` vs `Ulong`
Sometimes you can simply reduce 2 bytes by using this trick:
```
DIM r AS Integer
vs
DIM r AS Ulong
```
This works on most occassions.
]