Last active
January 29, 2025 23:02
-
-
Save m0rjc/f835116c23f2151e4e9182f534a7dd98 to your computer and use it in GitHub Desktop.
Spike PRIME Experiments
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# This is my quick solution to the LEGE Spike PRIME Brain Game task. | |
# See https://education.lego.com/en-gb/lessons/prime-life-hacks/brain-game/ | |
# | |
# The code has morphed a litle in experimenting. I've added hinting to the display | |
# to make the game easier for example. I've changed the puzzle to be randomly generated | |
# and changed the trigger to load the stick to use the colour sensor. | |
# | |
# The player loads the answer stick by pushing it into the creature's mouth. The motor | |
# will start as soon as the stick is detected. | |
# | |
# The creature will indicate the number of tiles of the correct colour and position. | |
# It also shows a hint which is a graphical representation of the stick with correct | |
# positions highlighted. (This is set by constant SHOW_HINT in code) | |
# | |
# The user adjusts the stick and tries again until all colours are matched. Then a | |
# victory is shown and a new puzzle generated for the next game. | |
# | |
# The bricks are those used in the original LEGO lesson plan. The stick has one brick of | |
# each of the colours red, yellow, gree, blue and magenta. | |
# | |
from hub import light_matrix, button, port | |
import color | |
import color_sensor | |
import motor | |
from app import sound | |
from random import randrange | |
import runloop | |
NUMBER_OF_BRICKS = 5 | |
AVAILABLE_COLOURS = [color.RED, color.YELLOW, color.GREEN, color.BLUE, color.MAGENTA] | |
NUMBER_OF_COLOURS = len(AVAILABLE_COLOURS) | |
SHOW_HINT = True | |
# Create a colour puzzle. | |
# This function modifies the list passed to it. | |
# Lists are passed by reference in Python. I have chosen to do this because if I was programming | |
# an embedded system I'd be concerned about memory usage and performance. I clear the list and regrow | |
# it, so that optimisation seems out of the window. | |
def createColourPuzzle(targetList): | |
tmp = AVAILABLE_COLOURS.copy() | |
targetList.clear() | |
for index in range(NUMBER_OF_BRICKS): | |
chosen = tmp[randrange(0, len(tmp))] | |
tmp.remove(chosen) | |
targetList.append(chosen); | |
# Load the stick into the creature's mouth ready to read | |
async def loadStick(): | |
await sound.play('Bite') | |
await motor.run_for_time(port.A, 1000, -500) | |
await sound.play('Bite') | |
await motor.run_for_time(port.A, 1000, -500) | |
await sound.play('Burp 3') | |
# Read a colour then advance the stick to the next block | |
# @returns the colour read from the stick. | |
async def readColourAndAdvance(): | |
await runloop.sleep_ms(500) | |
result = color_sensor.color(port.B) | |
await runloop.sleep_ms(500) | |
motor.run_for_degrees(port.A, 95, 500) | |
return result | |
# Load and read the whole stick | |
# @param targetList the list to write colours to. | |
async def readStick(targetList): | |
await loadStick() | |
targetList.clear() | |
for index in range(NUMBER_OF_BRICKS): | |
targetList.append(await readColourAndAdvance()) | |
# Calculate the score for the given stick against the puzzle. | |
# The output is the number of bricks of the correct colour and position | |
def scoreStick(puzzle, stick): | |
score = 0 | |
for index in range(NUMBER_OF_BRICKS): | |
if(puzzle[index] == stick[index]): | |
score = score + 1 | |
return score | |
async def main(): | |
# write your code here | |
await light_matrix.write("Hi!") | |
puzzle = [] | |
answer = [] | |
createColourPuzzle(puzzle) | |
print('Puzzle: ', puzzle) | |
while True: | |
await runloop.until(lambda: color_sensor.color(port.B) > 0) | |
light_matrix.clear() | |
await readStick(answer) | |
print('----------------') | |
print('Puzzle:', puzzle) | |
print('Stick: ', answer) | |
score = scoreStick(puzzle, answer) | |
print('Score: ', score) | |
if(score == 5): | |
light_matrix.show_image(light_matrix.IMAGE_FABULOUS) | |
await sound.play('Win') | |
createColourPuzzle(puzzle) | |
print('New Puzzle: ', puzzle) | |
elif(score == 0): | |
light_matrix.show_image(light_matrix.IMAGE_MEH) | |
await sound.play('Oops') | |
else: | |
light_matrix.clear() | |
for x in range(score): | |
for y in range(x+1): | |
light_matrix.set_pixel(x,4-y,100) | |
await sound.play('Coin') | |
if(SHOW_HINT): | |
for x in range(NUMBER_OF_BRICKS): | |
if(puzzle[x] == answer[x]): | |
light_matrix.set_pixel(x,0,60) | |
else: | |
light_matrix.set_pixel(x,0,10) | |
runloop.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# A demonstration of the three sorting algorithms in the GCSE Computer Science syllabus | |
# using the LEGO PRIME matrix display. | |
# | |
from hub import light_matrix | |
import runloop | |
import random | |
# | |
# Shuffle a list | |
# | |
def shuffle(list): | |
output = [] | |
while(len(list) > 0): | |
index = random.randrange(0,len(list)) | |
value = list[index] | |
list.remove(value) | |
output.append(value) | |
return output | |
# | |
# Swap the element at position pos in the list with the next element | |
# | |
def swap_with_next(list,pos): | |
tmp = list[pos] | |
list[pos] = list[pos + 1] | |
list[pos + 1] = tmp | |
# | |
# Animate the state of the list higlighting any cells in the highlights list | |
# | |
async def animate_comparison(values, highlights): | |
highlighted = [100 if x in highlights else values[x] for x in range(25)] | |
light_matrix.show(highlighted) | |
await runloop.sleep_ms(50) | |
async def animate_result_step(values): | |
light_matrix.show(values) | |
await runloop.sleep_ms(10) | |
# | |
# Demonstrate the bubble sort | |
# | |
async def bubble_sort(values): | |
for top in range(25): | |
for pos in range(24-top): | |
await animate_comparison(values,[pos,pos+1]) | |
if(values[pos] > values[pos + 1]): | |
swap_with_next(values, pos) | |
await animate_result_step(values) | |
# | |
# Demonstrate the merge sort, using a depth first recursive algorithm. | |
# GCSE teaches a breadth first algorithm, but depth first is easier to code. | |
# | |
async def merge_sort(list, start, end): | |
if(end - start is 1): | |
return | |
if(end - start is 2): | |
await animate_comparison(list,[start,start+1]) | |
if(list[end-1] < list[start]): | |
swap_with_next(list,start) | |
await animate_result_step(list) | |
return | |
# Recursively sort the two half lists | |
mid = (start + end) >> 1 | |
await merge_sort(list, start, mid) | |
await merge_sort(list, mid, end) | |
# Now merge them | |
tmp = list.copy() | |
outptr = start | |
read1 = start | |
read2 = mid | |
while(outptr < end): | |
await animate_comparison(list,[read1,read2]) | |
value1 = tmp[read1] if read1 < mid else 10000 | |
value2 = tmp[read2] if read2 < end else 10000 | |
if(value1 < value2): | |
list[outptr] = value1 | |
read1 = read1 + 1 | |
else: | |
list[outptr] = value2 | |
read2 = read2 + 1 | |
outptr = outptr + 1 | |
await animate_result_step(list) | |
# | |
# Demonstrate insertion sort. | |
# The output list is maintained at 25 long here so that it can be used | |
# to populate the display. | |
# | |
async def insertion_sort(list): | |
tmp = list.copy() | |
list = [0 for x in range(25)] | |
for ptr in range(25): | |
value = tmp[ptr] | |
insertion_point = 0 | |
while(list[insertion_point] < value and insertion_point < ptr): | |
await animate_comparison(list, [insertion_point]) | |
insertion_point = insertion_point + 1 | |
list.insert(insertion_point, value) | |
list.pop() # maintain 25 long | |
await animate_result_step(list) | |
async def main(): | |
values = [int(x*3) for x in range(25)] | |
light_matrix.show(values) | |
await runloop.sleep_ms(1000) | |
while True: | |
# Bubble Sort | |
await light_matrix.write('Bubble Sort') | |
values = shuffle(values); | |
light_matrix.show(values) | |
await bubble_sort(values) | |
await runloop.sleep_ms(1000) | |
# Merge Sort | |
await light_matrix.write('Merge Sort') | |
values = shuffle(values) | |
light_matrix.show(values) | |
await merge_sort(values, 0, 25) | |
await runloop.sleep_ms(1000) | |
# Insertion Sort | |
await light_matrix.write('Insertion Sort') | |
values = shuffle(values) | |
light_matrix.show(values) | |
await insertion_sort(values) | |
await runloop.sleep_ms(1000) | |
runloop.run(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment