# ========================================================================== #
# These globals should be part of some library, hidden from the user
# The only exposed functions are: get_position, get_world_dimensions,
# move, measure, swap, and the directions (which should ideally be an enum)
_grid = [[4, 5, 2, 2],
[1, 3, 6, 4]]
_height = len(_grid)
_length = len(_grid[0])
def get_world_dimensions():
return (_length, _height)
_x = 0
_y = 0
def get_position():
return (_x, _y)
North = "N"
South = "S"
East = "E"
West = "W"
# Return the value of the current cell, or the one directly in the specified direction
def measure(direction=None):
if direction is None:
return _grid[_y][_x]
# Hacky solution to get the value in that direction
# (probably not how it would actually be implemented)
x, y = get_position()
move(direction)
val = measure()
move_to(x, y)
return val
# Move one cell in the specified direction
def move(direction):
global _x, _y
if direction == North:
_y = (_y + 1) % _height
elif direction == South:
_y = (_y - 1) % _height
elif direction == East:
_x = (_x + 1) % _length
elif direction == West:
_x = (_x - 1) % _length
else:
raise ValueError(f"{direction} is not a valid direction to move in")
# Move the values of the current cell and the one in the specified direction
# But not wrapping around the edges
def swap(direction):
# also kinda hacky, but this is not the point
if direction == North and _y + 1 < _height:
_grid[_y][_x], _grid[_y + 1][_x] = _grid[_y + 1][_x], _grid[_y][_x]
elif direction == South and _y > 0:
_grid[_y][_x], _grid[_y - 1][_x] = _grid[_y - 1][_x], _grid[_y][_x]
elif direction == East and _x + 1 < _length:
_grid[_y][_x], _grid[_y][_x + 1] = _grid[_y][_x + 1], _grid[_y][_x]
elif direction == West and _x > 0:
_grid[_y][_x], _grid[_y][_x - 1] = _grid[_y][_x - 1], _grid[_y][_x]
else:
raise ValueError(f"{direction} is not a valid direction to swap in from position {(_x, _y)}")
# ========================================================================== #
# Not a part of the API, but convenient for me here
# The user could make something with the same effect, through get_position() and move()
def move_to(x, y):
global _x, _y
_x = x
_y = y
# ========================================================================== #
# My solution
# Assumes everything below and everything at this height to the left,
# is sorted in increasing order of going along the first row first, then the second and so on
# Inserts the current cell, and returns the pointer to this cell
def insert():
x, y = get_position()
val = measure()
if y > 0:
# Takes the shortcut of pulling it down if it should be there
# Then ensures it is in place, and continues with whatever was pulled up
if measure(South) > val:
swap(South)
move(South)
insert()
move(North)
val = measure()
if x == 0:
move(West)
if measure(South) <= val:
move(East)
return
# In this situation, we should move this all the way to the right and down once
# This is the best I could come up with for that
m, n = get_world_dimensions()
swap(South)
swap(West)
for i in range(2, m):
move(West)
swap(West)
for i in range(2, m):
swap(East)
move(East)
swap(South)
move(South)
insert()
move(North)
move(East)
if x > 0 and measure(West) > val:
swap(West)
move(West)
insert()
move(East)
# Goal: move the values around such that ever row and every column are individually sorted
# Idea: "Standard" insertion sort, as if the grid was just one long array
# where the first `m` elements are the ones in row 0, then comes row 1 and so on
# This is already an O((nm)^2) algorithm in the ideal sense of being able to swap elements in constant time,
# and even worse here, having to deal with the edges of the grid.
def insertion_sort():
move_to(0, 0)
m, n = get_world_dimensions()
for i in range(n):
for j in range(m):
insert()
move(East)
move(North)
print("Before")
print(_grid)
insertion_sort()
print("After")
print(_grid)
IyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAjCiMgVGhlc2UgZ2xvYmFscyBzaG91bGQgYmUgcGFydCBvZiBzb21lIGxpYnJhcnksIGhpZGRlbiBmcm9tIHRoZSB1c2VyCiMgVGhlIG9ubHkgZXhwb3NlZCBmdW5jdGlvbnMgYXJlOiBnZXRfcG9zaXRpb24sIGdldF93b3JsZF9kaW1lbnNpb25zLAojIG1vdmUsIG1lYXN1cmUsIHN3YXAsIGFuZCB0aGUgZGlyZWN0aW9ucyAod2hpY2ggc2hvdWxkIGlkZWFsbHkgYmUgYW4gZW51bSkKX2dyaWQgPSBbWzQsIDUsIDIsIDJdLAogICAgICAgICBbMSwgMywgNiwgNF1dCl9oZWlnaHQgPSBsZW4oX2dyaWQpCl9sZW5ndGggPSBsZW4oX2dyaWRbMF0pCmRlZiBnZXRfd29ybGRfZGltZW5zaW9ucygpOgogICAgcmV0dXJuIChfbGVuZ3RoLCBfaGVpZ2h0KQpfeCA9IDAKX3kgPSAwCmRlZiBnZXRfcG9zaXRpb24oKToKICAgIHJldHVybiAoX3gsIF95KQoKTm9ydGggPSAiTiIKU291dGggPSAiUyIKRWFzdCA9ICJFIgpXZXN0ID0gIlciCgojIFJldHVybiB0aGUgdmFsdWUgb2YgdGhlIGN1cnJlbnQgY2VsbCwgb3IgdGhlIG9uZSBkaXJlY3RseSBpbiB0aGUgc3BlY2lmaWVkIGRpcmVjdGlvbgpkZWYgbWVhc3VyZShkaXJlY3Rpb249Tm9uZSk6CiAgICBpZiBkaXJlY3Rpb24gaXMgTm9uZToKICAgICAgICByZXR1cm4gX2dyaWRbX3ldW194XQogICAgIyBIYWNreSBzb2x1dGlvbiB0byBnZXQgdGhlIHZhbHVlIGluIHRoYXQgZGlyZWN0aW9uCiAgICAjIChwcm9iYWJseSBub3QgaG93IGl0IHdvdWxkIGFjdHVhbGx5IGJlIGltcGxlbWVudGVkKQogICAgeCwgeSA9IGdldF9wb3NpdGlvbigpCiAgICBtb3ZlKGRpcmVjdGlvbikKICAgIHZhbCA9IG1lYXN1cmUoKQogICAgbW92ZV90byh4LCB5KQogICAgcmV0dXJuIHZhbAoKIyBNb3ZlIG9uZSBjZWxsIGluIHRoZSBzcGVjaWZpZWQgZGlyZWN0aW9uCmRlZiBtb3ZlKGRpcmVjdGlvbik6CiAgICBnbG9iYWwgX3gsIF95CiAgICBpZiBkaXJlY3Rpb24gPT0gTm9ydGg6CiAgICAgICAgX3kgPSAoX3kgKyAxKSAlIF9oZWlnaHQKICAgIGVsaWYgZGlyZWN0aW9uID09IFNvdXRoOgogICAgICAgIF95ID0gKF95IC0gMSkgJSBfaGVpZ2h0CiAgICBlbGlmIGRpcmVjdGlvbiA9PSBFYXN0OgogICAgICAgIF94ID0gKF94ICsgMSkgJSBfbGVuZ3RoCiAgICBlbGlmIGRpcmVjdGlvbiA9PSBXZXN0OgogICAgICAgIF94ID0gKF94IC0gMSkgJSBfbGVuZ3RoCiAgICBlbHNlOgogICAgICAgIHJhaXNlIFZhbHVlRXJyb3IoZiJ7ZGlyZWN0aW9ufSBpcyBub3QgYSB2YWxpZCBkaXJlY3Rpb24gdG8gbW92ZSBpbiIpCgojIE1vdmUgdGhlIHZhbHVlcyBvZiB0aGUgY3VycmVudCBjZWxsIGFuZCB0aGUgb25lIGluIHRoZSBzcGVjaWZpZWQgZGlyZWN0aW9uCiMgQnV0IG5vdCB3cmFwcGluZyBhcm91bmQgdGhlIGVkZ2VzCmRlZiBzd2FwKGRpcmVjdGlvbik6CiAgICAjIGFsc28ga2luZGEgaGFja3ksIGJ1dCB0aGlzIGlzIG5vdCB0aGUgcG9pbnQKICAgIGlmIGRpcmVjdGlvbiA9PSBOb3J0aCBhbmQgX3kgKyAxIDwgX2hlaWdodDoKICAgICAgICBfZ3JpZFtfeV1bX3hdLCBfZ3JpZFtfeSArIDFdW194XSA9IF9ncmlkW195ICsgMV1bX3hdLCBfZ3JpZFtfeV1bX3hdCiAgICBlbGlmIGRpcmVjdGlvbiA9PSBTb3V0aCBhbmQgX3kgPiAwOgogICAgICAgIF9ncmlkW195XVtfeF0sIF9ncmlkW195IC0gMV1bX3hdID0gX2dyaWRbX3kgLSAxXVtfeF0sIF9ncmlkW195XVtfeF0KICAgIGVsaWYgZGlyZWN0aW9uID09IEVhc3QgYW5kIF94ICsgMSA8IF9sZW5ndGg6CiAgICAgICAgX2dyaWRbX3ldW194XSwgX2dyaWRbX3ldW194ICsgMV0gPSBfZ3JpZFtfeV1bX3ggKyAxXSwgX2dyaWRbX3ldW194XQogICAgZWxpZiBkaXJlY3Rpb24gPT0gV2VzdCBhbmQgX3ggPiAwOgogICAgICAgIF9ncmlkW195XVtfeF0sIF9ncmlkW195XVtfeCAtIDFdID0gX2dyaWRbX3ldW194IC0gMV0sIF9ncmlkW195XVtfeF0KICAgIGVsc2U6CiAgICAgICAgcmFpc2UgVmFsdWVFcnJvcihmIntkaXJlY3Rpb259IGlzIG5vdCBhIHZhbGlkIGRpcmVjdGlvbiB0byBzd2FwIGluIGZyb20gcG9zaXRpb24geyhfeCwgX3kpfSIpCiAgICAgICAgCiAgICAKCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gIwoKIyBOb3QgYSBwYXJ0IG9mIHRoZSBBUEksIGJ1dCBjb252ZW5pZW50IGZvciBtZSBoZXJlCiMgVGhlIHVzZXIgY291bGQgbWFrZSBzb21ldGhpbmcgd2l0aCB0aGUgc2FtZSBlZmZlY3QsIHRocm91Z2ggZ2V0X3Bvc2l0aW9uKCkgYW5kIG1vdmUoKQpkZWYgbW92ZV90byh4LCB5KToKICAgIGdsb2JhbCBfeCwgX3kKICAgIF94ID0geAogICAgX3kgPSB5CgojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICMKIyBNeSBzb2x1dGlvbgoKIyBBc3N1bWVzIGV2ZXJ5dGhpbmcgYmVsb3cgYW5kIGV2ZXJ5dGhpbmcgYXQgdGhpcyBoZWlnaHQgdG8gdGhlIGxlZnQsIAojIGlzIHNvcnRlZCBpbiBpbmNyZWFzaW5nIG9yZGVyIG9mIGdvaW5nIGFsb25nIHRoZSBmaXJzdCByb3cgZmlyc3QsIHRoZW4gdGhlIHNlY29uZCBhbmQgc28gb24KIyBJbnNlcnRzIHRoZSBjdXJyZW50IGNlbGwsIGFuZCByZXR1cm5zIHRoZSBwb2ludGVyIHRvIHRoaXMgY2VsbApkZWYgaW5zZXJ0KCk6CiAgICB4LCB5ID0gZ2V0X3Bvc2l0aW9uKCkKICAgIHZhbCA9IG1lYXN1cmUoKQogICAgaWYgeSA+IDA6CiAgICAgICAgIyBUYWtlcyB0aGUgc2hvcnRjdXQgb2YgcHVsbGluZyBpdCBkb3duIGlmIGl0IHNob3VsZCBiZSB0aGVyZQogICAgICAgICMgVGhlbiBlbnN1cmVzIGl0IGlzIGluIHBsYWNlLCBhbmQgY29udGludWVzIHdpdGggd2hhdGV2ZXIgd2FzIHB1bGxlZCB1cAogICAgICAgIGlmIG1lYXN1cmUoU291dGgpID4gdmFsOgogICAgICAgICAgICBzd2FwKFNvdXRoKQogICAgICAgICAgICBtb3ZlKFNvdXRoKQogICAgICAgICAgICBpbnNlcnQoKQogICAgICAgICAgICBtb3ZlKE5vcnRoKQogICAgICAgICAgICB2YWwgPSBtZWFzdXJlKCkKICAgICAgICBpZiB4ID09IDA6CiAgICAgICAgICAgIG1vdmUoV2VzdCkKICAgICAgICAgICAgaWYgbWVhc3VyZShTb3V0aCkgPD0gdmFsOgogICAgICAgICAgICAgICAgbW92ZShFYXN0KQogICAgICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgICAgICMgSW4gdGhpcyBzaXR1YXRpb24sIHdlIHNob3VsZCBtb3ZlIHRoaXMgYWxsIHRoZSB3YXkgdG8gdGhlIHJpZ2h0IGFuZCBkb3duIG9uY2UKICAgICAgICAgICAgIyBUaGlzIGlzIHRoZSBiZXN0IEkgY291bGQgY29tZSB1cCB3aXRoIGZvciB0aGF0CiAgICAgICAgICAgIG0sIG4gPSBnZXRfd29ybGRfZGltZW5zaW9ucygpCiAgICAgICAgICAgIHN3YXAoU291dGgpCiAgICAgICAgICAgIHN3YXAoV2VzdCkKICAgICAgICAgICAgZm9yIGkgaW4gcmFuZ2UoMiwgbSk6CiAgICAgICAgICAgICAgICBtb3ZlKFdlc3QpCiAgICAgICAgICAgICAgICBzd2FwKFdlc3QpCiAgICAgICAgICAgIGZvciBpIGluIHJhbmdlKDIsIG0pOgogICAgICAgICAgICAgICAgc3dhcChFYXN0KQogICAgICAgICAgICAgICAgbW92ZShFYXN0KQogICAgICAgICAgICBzd2FwKFNvdXRoKQogICAgICAgICAgICBtb3ZlKFNvdXRoKQogICAgICAgICAgICBpbnNlcnQoKQogICAgICAgICAgICBtb3ZlKE5vcnRoKQogICAgICAgICAgICBtb3ZlKEVhc3QpCiAgICBpZiB4ID4gMCBhbmQgbWVhc3VyZShXZXN0KSA+IHZhbDoKICAgICAgICBzd2FwKFdlc3QpCiAgICAgICAgbW92ZShXZXN0KQogICAgICAgIGluc2VydCgpCiAgICAgICAgbW92ZShFYXN0KQogICAgICAgICAgICAKCgojIEdvYWw6IG1vdmUgdGhlIHZhbHVlcyBhcm91bmQgc3VjaCB0aGF0IGV2ZXIgcm93IGFuZCBldmVyeSBjb2x1bW4gYXJlIGluZGl2aWR1YWxseSBzb3J0ZWQKIyBJZGVhOiAiU3RhbmRhcmQiIGluc2VydGlvbiBzb3J0LCBhcyBpZiB0aGUgZ3JpZCB3YXMganVzdCBvbmUgbG9uZyBhcnJheQojIHdoZXJlIHRoZSBmaXJzdCBgbWAgZWxlbWVudHMgYXJlIHRoZSBvbmVzIGluIHJvdyAwLCB0aGVuIGNvbWVzIHJvdyAxIGFuZCBzbyBvbgojIFRoaXMgaXMgYWxyZWFkeSBhbiBPKChubSleMikgYWxnb3JpdGhtIGluIHRoZSBpZGVhbCBzZW5zZSBvZiBiZWluZyBhYmxlIHRvIHN3YXAgZWxlbWVudHMgaW4gY29uc3RhbnQgdGltZSwKIyBhbmQgZXZlbiB3b3JzZSBoZXJlLCBoYXZpbmcgdG8gZGVhbCB3aXRoIHRoZSBlZGdlcyBvZiB0aGUgZ3JpZC4KZGVmIGluc2VydGlvbl9zb3J0KCk6CiAgICBtb3ZlX3RvKDAsIDApCiAgICBtLCBuID0gZ2V0X3dvcmxkX2RpbWVuc2lvbnMoKQogICAgZm9yIGkgaW4gcmFuZ2Uobik6CiAgICAgICAgZm9yIGogaW4gcmFuZ2UobSk6CiAgICAgICAgICAgIGluc2VydCgpCiAgICAgICAgICAgIG1vdmUoRWFzdCkKICAgICAgICBtb3ZlKE5vcnRoKQoKCnByaW50KCJCZWZvcmUiKQpwcmludChfZ3JpZCkKCmluc2VydGlvbl9zb3J0KCkKCnByaW50KCJBZnRlciIpCnByaW50KF9ncmlkKQ==