Skip to content

Instantly share code, notes, and snippets.

@m0rjc
Last active January 29, 2025 23:02
Show Gist options
  • Save m0rjc/f835116c23f2151e4e9182f534a7dd98 to your computer and use it in GitHub Desktop.
Save m0rjc/f835116c23f2151e4e9182f534a7dd98 to your computer and use it in GitHub Desktop.
Spike PRIME Experiments
#
# 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())
#
# 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