Piotr Czajkowski 6 months ago
parent
commit
86556628da
2 changed files with 262 additions and 0 deletions
  1. 136 0
      20200510/epidemic.js
  2. 126 0
      20200510/epidemic.py

+ 136 - 0
20200510/epidemic.js

@@ -0,0 +1,136 @@
+const WIDTH = 8;
+const HEIGHT = 8;
+
+// https://www.coding-dojo-silesia.pl/golf
+
+function point_free(x, y, people) {
+	const pLength = people.length;
+	for (let i = 0; i < pLength; i++) {
+		const person = people[i];
+		if (x === person.x && y === person.y)
+			return false;
+	}
+
+	return true;
+}
+
+function check_neighborhood(person, people) {
+	const pLength = people.length;
+	for (let i = 0; i < pLength; i++) {
+		const otherPerson = people[i];
+		if ((otherPerson.x >= person.x-1 && otherPerson.x <= person.x+1) && (otherPerson.y >= person.y-1 && otherPerson.y <= person.y+1) && otherPerson.s === 'S') {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+function next_iteration(people) {
+	people.forEach(function(person, _) { // iterate in a sequence
+		cure(person);
+
+		if (person.s === 'S') person.i++;
+
+		person.n = gen_n(person.n);
+		[new_x, new_y] = gen_new_cords(person);
+		if (point_free(new_x, new_y, people) && person.q === 0) {
+			person.x = new_x;
+			person.y = new_y;
+		}
+
+		if (person.s === 'H' && check_neighborhood(person, people)) {
+			// https://en.wikipedia.org/wiki/Moore_neighborhood
+			person.s = 'S';
+		}
+	});
+
+	return people;
+}
+
+function cure(person) {
+	if (person.s === 'S' && person.i > 13) {
+		person.s = 'R';
+		person.i = 1;
+	}
+}
+
+function gen_n(n) {
+	n ^= n << BigInt(13);
+	n ^= n >> BigInt(17);
+	n ^= n << BigInt(5);
+	return n % BigInt(1 << 30);
+}
+
+function gen_new_cords(person) {
+	x = person.x;
+	y = person.y;
+	switch(person.n % BigInt(4)) {
+		case BigInt(0): x++; break;
+		case BigInt(1): x--; break;
+		case BigInt(2): y++; break;
+		case BigInt(3): y--; break;
+	}
+	// wrap points, like in pacman game
+	if (x >= WIDTH) {
+		x -= WIDTH;
+	} else if (x < 0) {
+		x += WIDTH;
+	}
+
+	if (y >= HEIGHT) {
+		y -= HEIGHT;
+	} else if (y < 0) {
+		y += HEIGHT;
+	}
+
+	return [x, y];
+}
+
+function get_people(peopleString) {
+	peopleUnparsed = peopleString.split(",");
+
+	let people = [];
+	peopleUnparsed.forEach(function(item, _) {
+		let person = {};
+		person.x = Number(item[0]);
+		person.y = Number(item[1]);
+		person.s = item[2];
+		person.q = Number(item[3]);
+
+		person.n = BigInt((person.x << 2) ^ 7 * (person.y << 3) ^ 5);
+		person.i = 1;
+
+		people.push(person);
+	});
+
+	return people;
+}
+
+function print_field(P) {
+	for (let i = 0; i < HEIGHT; i++) {
+		let string = '';
+		for (let j = 0; j < WIDTH; j++) {
+			const person = P.find(p => p.x === j && p.y === i);
+			if (person === undefined)
+				string += '.';
+			else
+				string += person.s;
+		}
+		console.log(string);
+	}
+}
+
+function main() {
+	const iterations = process.argv[2];
+	const peopleUnparsed = process.argv[3];
+
+	let people = get_people(peopleUnparsed);
+
+	for (let i = 0; i < iterations; i++) {
+		people = next_iteration(people);
+	}
+	print_field(people);
+}
+
+main();

+ 126 - 0
20200510/epidemic.py

@@ -0,0 +1,126 @@
+import sys
+
+# https://www.coding-dojo-silesia.pl/golf
+
+WIDTH = 8
+HEIGHT = 8
+
+class Person:
+    def __init__(self, x, y, s, q):
+        self.x = int(x)
+        self.y = int(y)
+        self.s = s
+        self.q = int(q)
+
+        self.n = (self.x << 2) ^ 7 * (self.y << 3) ^ 5
+        self.i = 1
+
+
+def point_free(x, y, people):
+    for person in people:
+        if x == person.x and y == person.y:
+            return False
+
+    return True
+
+def check_neighborhood(person, people):
+    for otherPerson in people:
+        if (otherPerson.x >= person.x-1 and otherPerson.x <= person.x+1) and (otherPerson.y >= person.y-1 and otherPerson.y <= person.y+1) and otherPerson.s == 'S':
+            return True
+
+    return False
+
+def next_iteration(people):
+    for person in people:
+        cure(person);
+
+        if person.s == 'S':
+            person.i += 1
+
+        person.n = gen_n(person.n)
+        [new_x, new_y] = gen_new_cords(person)
+        if point_free(new_x, new_y, people) and person.q == 0:
+            person.x = new_x
+            person.y = new_y
+
+        if person.s == 'H' and check_neighborhood(person, people):
+            person.s = 'S'
+
+    return people
+
+def cure(person):
+    if person.s == 'S' and person.i > 13:
+        person.s = 'R'
+        person.i = 1
+
+def gen_n(n):
+    n ^= n << 13
+    n ^= n >> 17
+    n ^= n << 5
+
+    return n % (1 << 30)
+
+def gen_new_cords(person):
+    x = person.x
+    y = person.y
+
+    check = person.n % 4
+
+    if check == 0:
+        x += 1
+
+    if check == 1:
+        x -= 1
+
+    if check == 2:
+        y += 1
+
+    if check == 3:
+        y -= 1
+
+    if x >= WIDTH:
+        x -= WIDTH
+    elif x < 0:
+        x += WIDTH
+
+    if y >= HEIGHT:
+        y -= HEIGHT
+    elif y < 0:
+        y += HEIGHT
+
+    return [x, y]
+
+def get_people(peopleString):
+    peopleUnparsed = peopleString.split(",")
+
+    people = []
+    for item in peopleUnparsed:
+        person = Person(item[0], item[1], item[2], item[3])
+        people.append(person)
+
+    return people
+
+def print_field(people):
+    for i in range(0, HEIGHT):
+        string = ''
+        for j in range(0, WIDTH):
+            person = [x for x in people if x.x == j and x.y == i]
+            if len(person) == 0 :
+                string += '.'
+            else:
+                string += person[0].s
+
+        print(string)
+
+def main():
+    iterations = int(sys.argv[1])
+    peopleUnparsed = sys.argv[2]
+
+    people = get_people(peopleUnparsed)
+
+    for i in range(0, iterations):
+        people = next_iteration(people)
+
+    print_field(people)
+
+main()