Skip to content

Commit 7e65b18

Browse files
committed
six new lessons, mostly about lists
1 parent ef632b8 commit 7e65b18

File tree

6 files changed

+381
-0
lines changed

6 files changed

+381
-0
lines changed

lessons/0007-conditions.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Intro to Condition Optimization
2+
Conditions are ripe for optimization because TI-BASIC is very flexible with booleans.
3+
4+
Recall that TI-BASIC's conditionals and logical operators treat every nonzero real number as a "truthy" value and zero as a "falsy" value.
5+
6+
Recognizing this, use a logical operator to save two bytes off the provided program.
7+
```json
8+
{
9+
"id": 7,
10+
"requirements": [1],
11+
"name": "Intro to Condition Optimization",
12+
"starting_program": "If L1(2)=0\nDisp A",
13+
"required_savings": 2,
14+
"tests": [
15+
{
16+
"regex": "If not\\(L1\\(2[\\n:]Disp A"
17+
}
18+
]
19+
}
20+
```
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Condition Optimizations: Avoid Ifs (easy)
2+
Like some other languages, TI-BASIC uses 1 and 0 to represent boolean `true` and `false`. Because of this, we can often use conditions inside of expressions to replace if statements:
3+
```
4+
If not(A
5+
B+1->B
6+
```
7+
can become
8+
```
9+
B+not(A->B
10+
```
11+
<!-- Too many possibilities to test with regex... just better to behavior-test -->
12+
```json
13+
{
14+
"id": 8,
15+
"name": "Condition Optimizations: Avoid Ifs",
16+
"requirements": [7],
17+
"brief_description": "Optimize this character movement routine",
18+
"starting_program": "If K=24\nI-1->I\nIf K=26\nI+1->I\nIf K=25\nJ-1->J\nIf K=34\nJ+1->J\nIf I<0\n0->I\nIf I>10\n10->I\nIf J<0\n0->J\nIf J>10\n10->J",
19+
"required_savings": 40,
20+
"tests": [
21+
[
22+
{
23+
"input": [
24+
{"name": "K", "value": 24},
25+
{"name": "I", "value": 0},
26+
{"name": "J", "value": 5}
27+
],
28+
"output": [
29+
{"name": "I", "value": 0},
30+
{"name": "J", "value": 5}
31+
]
32+
},
33+
{
34+
"input": [
35+
{"name": "K", "value": 24},
36+
{"name": "I", "value": 1},
37+
{"name": "J", "value": 5}
38+
],
39+
"output": [
40+
{"name": "I", "value": 0},
41+
{"name": "J", "value": 5}
42+
]
43+
},
44+
{
45+
"input": [
46+
{"name": "K", "value": 34},
47+
{"name": "I", "value": 1},
48+
{"name": "J", "value": 5}
49+
],
50+
"output": [
51+
{"name": "I", "value": 1},
52+
{"name": "J", "value": 6}
53+
]
54+
},
55+
{
56+
"input": [
57+
{"name": "K", "value": 34},
58+
{"name": "I", "value": 1},
59+
{"name": "J", "value": 10}
60+
],
61+
"output": [
62+
{"name": "I", "value": 1},
63+
{"name": "J", "value": 10}
64+
]
65+
},
66+
{
67+
"input": [
68+
{"name": "K", "value": 26},
69+
{"name": "I", "value": 1},
70+
{"name": "J", "value": 10}
71+
],
72+
"output": [
73+
{"name": "I", "value": 2},
74+
{"name": "J", "value": 10}
75+
]
76+
},
77+
{
78+
"input": [
79+
{"name": "K", "value": 26},
80+
{"name": "I", "value": 10},
81+
{"name": "J", "value": 10}
82+
],
83+
"output": [
84+
{"name": "I", "value": 10},
85+
{"name": "J", "value": 10}
86+
]
87+
},
88+
{
89+
"input": [
90+
{"name": "K", "value": 25},
91+
{"name": "I", "value": 10},
92+
{"name": "J", "value": 10}
93+
],
94+
"output": [
95+
{"name": "I", "value": 10},
96+
{"name": "J", "value": 9}
97+
]
98+
},
99+
{
100+
"input": [
101+
{"name": "K", "value": 25},
102+
{"name": "I", "value": 10},
103+
{"name": "J", "value": 0}
104+
],
105+
"output": [
106+
{"name": "I", "value": 10},
107+
{"name": "J", "value": 0}
108+
]
109+
}
110+
]
111+
]
112+
}
113+
```
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Condition Optimizations: Avoid Ifs (harder)
2+
Try to find a one-liner for this alternative character movement scheme.
3+
```
4+
X+(V>0)-(V<0->X
5+
If X>10
6+
1->X
7+
If X<1
8+
10->X
9+
```
10+
11+
_Hint: Find a transcendental function in the catalog that maps large positive values to 1, and large negative values to -1._
12+
```json
13+
{
14+
"id": 9,
15+
"name": "Condition Optimizations: Avoid Ifs (harder)",
16+
"starting_program": "X+(V>0)-(V<0->X\nIf X>10\n1->X\nIf X<1\n10->X",
17+
"requirements": [8],
18+
"required_savings": 15,
19+
"tests": [
20+
{
21+
"input": [{"name": "X", "value": 1}, {"name": "V", "value": -2}],
22+
"output": [{"name": "X", "value": 10}]
23+
},
24+
{
25+
"input": [{"name": "X", "value": 1}, {"name": "V", "value": 3}],
26+
"output": [{"name": "X", "value": 2}]
27+
},
28+
{
29+
"input": [{"name": "X", "value": 10}, {"name": "V", "value": 7}],
30+
"output": [{"name": "X", "value": 1}]
31+
},
32+
{
33+
"input": [{"name": "X", "value": 10}, {"name": "V", "value": -1}],
34+
"output": [{"name": "X", "value": 9}]
35+
},
36+
{
37+
"input": [{"name": "X", "value": 4}, {"name": "V", "value": 0}],
38+
"output": [{"name": "X", "value": 4}]
39+
}
40+
]
41+
}
42+
```
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Condition Optimizations: Use `max(`
2+
Quite regularly, programmers need to check many conditions simultaneously. In TI-BASIC, these checks can often be expressed using **condition vectorization** and an **aggregate function**.
3+
4+
With condition vectorization, we apply the same condition to every element of a carefully-constructed list. We then collect the results using our aggregate function (*usually* `sum(`, `max(`, or `min(`) to produce a meaningful result.
5+
6+
In this lesson we'll examine one possible aggregate function, `max(`. You can use `max(` on a list of conditions to check if _any_ of the conditions are true.
7+
8+
One application:
9+
```
10+
If A=1 or A=3 or A=4 or A=6
11+
```
12+
can become
13+
```
14+
If max(A={1,3,4,6
15+
```
16+
17+
Suppose A and B are positive integers and less than or equal to 9. How could we optimize this condition?
18+
```
19+
A=1 and B=2 or A=5 and B=9 or A=3 and B=4
20+
```
21+
22+
<!-- you can *definitely* do better than the bar I set here -->
23+
```json
24+
{
25+
"id": 10,
26+
"name": "Condition Optimizations: Use max(",
27+
"requirements": [8],
28+
"starting_program": "0\nIf A=1 and B=2 or A=5 and B=9 or A=3 and B=4\n1",
29+
"required_savings": 13,
30+
"tests": [
31+
[
32+
{
33+
"input": [{"name": "A", "value": 1}, {"name": "B", "value": 2}],
34+
"output": [{"name": "Ans", "value": 1}]
35+
},
36+
{
37+
"input": [{"name": "A", "value": 5}, {"name": "B", "value": 9}],
38+
"output": [{"name": "Ans", "value": 1}]
39+
},
40+
{
41+
"input": [{"name": "A", "value": 3}, {"name": "B", "value": 4}],
42+
"output": [{"name": "Ans", "value": 1}]
43+
},
44+
{
45+
"input": [{"name": "A", "value": 1}, {"name": "B", "value": 3}],
46+
"output": [{"name": "Ans", "value": 0}]
47+
},
48+
{
49+
"input": [{"name": "A", "value": 5}, {"name": "B", "value": 1}],
50+
"output": [{"name": "Ans", "value": 0}]
51+
},
52+
{
53+
"input": [{"name": "A", "value": 3}, {"name": "B", "value": 5}],
54+
"output": [{"name": "Ans", "value": 0}]
55+
},
56+
{
57+
"input": [{"name": "A", "value": 2}, {"name": "B", "value": 2}],
58+
"output": [{"name": "Ans", "value": 0}]
59+
},
60+
{
61+
"input": [{"name": "A", "value": 6}, {"name": "B", "value": 9}],
62+
"output": [{"name": "Ans", "value": 0}]
63+
},
64+
{
65+
"input": [{"name": "A", "value": 4}, {"name": "B", "value": 4}],
66+
"output": [{"name": "Ans", "value": 0}]
67+
}
68+
]
69+
]
70+
}
71+
```
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Condition Optimizations: Use `sum(` (easy)
2+
If all of the elements of a list are binary (0 or 1), you can use `sum(` to count how many are 1.
3+
4+
As a rare special case and illustrative example, `randBin(N,P)` is equivalent to `sum(P>rand(N`; i.e. it counts the number of times `P` is greater than the uniformly-distributed `rand` in a set of `N` samples.
5+
6+
In many golf problems, `randIntNoRep(` is useful when used in conjuction with `sum(`. Unlike the longer `cumSum(binomcdf(N-1,0` that produces a list of the numbers 1 through N in order, `randIntNoRep(1,N` produces the same numbers in a random order. We then apply some condition to every element of the list, and count the number of matches.
7+
8+
Use these techniques to count the number of distinct factors for a given integer 1<=N<=100.
9+
10+
_Hint: `fPart(`_
11+
<!-- 23 bytes {
12+
"regex": "sum\\(not\\(fPart\\(N/randIntNoRep\\(1,N"
13+
}-->
14+
```json
15+
{
16+
"id": 11,
17+
"name": "Condition Optimizations: Use sum( (easy)",
18+
"requirements": [9],
19+
"starting_program": "0\nFor(I,1,100\nAns+(0=remainder(N,I\nEnd",
20+
"required_savings": 13,
21+
"tests": [
22+
[
23+
{
24+
"input": [{"name": "N", "value": 1}],
25+
"output": [{"name": "Ans", "value": 1}]
26+
},
27+
{
28+
"input": [{"name": "N", "value": 2}],
29+
"output": [{"name": "Ans", "value": 2}]
30+
},
31+
{
32+
"input": [{"name": "N", "value": 4}],
33+
"output": [{"name": "Ans", "value": 3}]
34+
},
35+
{
36+
"input": [{"name": "N", "value": 5}],
37+
"output": [{"name": "Ans", "value": 2}]
38+
},
39+
{
40+
"input": [{"name": "N", "value": 16}],
41+
"output": [{"name": "Ans", "value": 5}]
42+
},
43+
{
44+
"input": [{"name": "N", "value": 24}],
45+
"output": [{"name": "Ans", "value": 8}]
46+
},
47+
{
48+
"input": [{"name": "N", "value": 49}],
49+
"output": [{"name": "Ans", "value": 3}]
50+
},
51+
{
52+
"input": [{"name": "N", "value": 91}],
53+
"output": [{"name": "Ans", "value": 4}]
54+
},
55+
{
56+
"input": [{"name": "N", "value": 92}],
57+
"output": [{"name": "Ans", "value": 6}]
58+
},
59+
{
60+
"input": [{"name": "N", "value": 100}],
61+
"output": [{"name": "Ans", "value": 9}]
62+
}
63+
]
64+
]
65+
}
66+
```
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Condition Optimizations: Use `sum(` (harder)
2+
Recall that every number has a unique octal (base-8) representation. Count the number of nonzero digits in this representation for a number 0 <= X <= 99999999 (base-10).
3+
<!-- this puzzle is inspired by a problem kerm posed & the main golf ideas here are due to lirto: https://www.cemetech.net/forum/viewtopic.php?p=236371#236371 -->
4+
```json
5+
{
6+
"id": 12,
7+
"name": "Condition Optimizations: Use sum( (harder)",
8+
"short_description": "Count the number of nonzero digits in the octal representation of a number 0 <= X <= 99999999 (base-10).",
9+
"starting_program": "0->C\nFor(I,0,1+logBASE(1+X,8\nremainder(X,8^I->R\nIf R\nC+1->C\nX-R->X\nEnd\nC",
10+
"required_savings": 33,
11+
"requirements": [11],
12+
"tests": [
13+
[
14+
{
15+
"input": [{"name": "X", "value": 0}],
16+
"output": [{"name": "Ans", "value": 0}]
17+
},
18+
{
19+
"input": [{"name": "X", "value": 1}],
20+
"output": [{"name": "Ans", "value": 1}]
21+
},
22+
{
23+
"input": [{"name": "X", "value": 8}],
24+
"output": [{"name": "Ans", "value": 1}]
25+
},
26+
{
27+
"input": [{"name": "X", "value": 64}],
28+
"output": [{"name": "Ans", "value": 1}]
29+
},
30+
{
31+
"input": [{"name": "X", "value": 640}],
32+
"output": [{"name": "Ans", "value": 2}]
33+
},
34+
{
35+
"input": [{"name": "X", "value": 134}],
36+
"output": [{"name": "Ans", "value": 2}]
37+
},
38+
{
39+
"input": [{"name": "X", "value": 136}],
40+
"output": [{"name": "Ans", "value": 2}]
41+
},
42+
{
43+
"input": [{"name": "X", "value": 80888}],
44+
"output": [{"name": "Ans", "value": 5}]
45+
},
46+
{
47+
"input": [{"name": "X", "value": 21777344}],
48+
"output": [{"name": "Ans", "value": 6}]
49+
},
50+
{
51+
"input": [{"name": "X", "value": 47640080}],
52+
"output": [{"name": "Ans", "value": 7}]
53+
},
54+
{
55+
"input": [{"name": "X", "value": 31777343}],
56+
"output": [{"name": "Ans", "value": 8}]
57+
},
58+
{
59+
"input": [{"name": "X", "value": 99999999}],
60+
"output": [{"name": "Ans", "value": 8}]
61+
},
62+
{
63+
"input": [{"name": "X", "value": 21380977}],
64+
"output": [{"name": "Ans", "value": 9}]
65+
}
66+
]
67+
]
68+
}
69+
```

0 commit comments

Comments
 (0)