1949–50 Scottish Football League
Statistics of the Scottish Football League in season 1949–50.
Scottish League Division One
Pos | Team | Pld | W | D | L | GF | GA | GD | Pts |
---|---|---|---|---|---|---|---|---|---|
1 | Rangers | 30 | 22 | 6 | 2 | 58 | 26 | +32 | 50 |
2 | Hibernian | 30 | 22 | 5 | 3 | 86 | 34 | +52 | 49 |
3 | Hearts | 30 | 20 | 3 | 7 | 86 | 40 | +46 | 43 |
4 | East Fife | 30 | 15 | 7 | 8 | 58 | 43 | +15 | 37 |
5 | Celtic | 30 | 14 | 7 | 9 | 51 | 50 | +1 | 35 |
6 | Dundee | 30 | 12 | 7 | 11 | 49 | 46 | +3 | 31 |
7 | Partick Thistle | 30 | 13 | 3 | 14 | 55 | 45 | +10 | 29 |
8 | Aberdeen | 30 | 11 | 4 | 15 | 48 | 56 | −8 | 26 |
9 | Raith Rovers | 30 | 9 | 8 | 13 | 45 | 54 | −9 | 26 |
10 | Motherwell | 30 | 10 | 5 | 15 | 53 | 58 | −5 | 25 |
11 | St Mirren | 30 | 8 | 9 | 13 | 42 | 49 | −7 | 25 |
12 | Third Lanark | 30 | 11 | 3 | 16 | 44 | 62 | −18 | 25 |
13 | Clyde | 30 | 10 | 4 | 16 | 56 | 73 | −17 | 24 |
14 | Falkirk | 30 | 7 | 10 | 13 | 48 | 72 | −24 | 24 |
15 | Queen of the South | 30 | 5 | 6 | 19 | 31 | 63 | −32 | 16 |
16 | Stirling Albion | 30 | 6 | 3 | 21 | 38 | 77 | −39 | 15 |
Source: RSSSF
Scottish League Division Two
Pos | Team | Pld | W | D | L | GF | GA | GD | Pts | Promotion or relegation |
---|---|---|---|---|---|---|---|---|---|---|
1 | Morton | 30 | 20 | 7 | 3 | 77 | 33 | +44 | 47 | Promotion to the 1950–51 First Division |
2 | Airdrieonians | 30 | 19 | 6 | 5 | 79 | 40 | +39 | 44 | |
3 | Dunfermline Athletic | 30 | 16 | 4 | 10 | 71 | 57 | +14 | 36 | |
4 | St Johnstone | 30 | 15 | 6 | 9 | 64 | 56 | +8 | 36 | |
5 | Cowdenbeath | 30 | 16 | 3 | 11 | 63 | 56 | +7 | 35 | |
6 | Hamilton Academical | 30 | 14 | 6 | 10 | 57 | 44 | +13 | 34 | |
7 | Dundee United | 30 | 14 | 5 | 11 | 74 | 56 | +18 | 33 | |
8 | Kilmarnock | 30 | 14 | 5 | 11 | 50 | 43 | +7 | 33 | |
9 | Queen's Park | 30 | 12 | 7 | 11 | 63 | 59 | +4 | 31 | |
10 | Forfar Athletic | 30 | 11 | 8 | 11 | 53 | 56 | −3 | 30 | |
11 | Albion Rovers | 30 | 10 | 7 | 13 | 49 | 61 | −12 | 27 | |
12 | Stenhousemuir | 30 | 8 | 8 | 14 | 54 | 72 | −18 | 24 | |
13 | Ayr United | 30 | 8 | 6 | 16 | 53 | 80 | −27 | 22 | |
14 | Arbroath | 30 | 5 | 9 | 16 | 47 | 69 | −22 | 19 | |
15 | Dumbarton | 30 | 6 | 4 | 20 | 39 | 62 | −23 | 16 | |
16 | Alloa Athletic | 30 | 5 | 3 | 22 | 47 | 96 | −49 | 13 |
Source:
gollark: > `import hashlib`Hashlib is still important!> `for entry, ubq323 in {**globals(), **__builtins__, **sys.__dict__, **locals(), CONSTANT: Entry()}.items():`Iterate over a bunch of things. I think only the builtins and globals are actually used.The stuff under here using `blake2s` stuff is actually written to be ridiculously unportable, to hinder analysis. This caused issues when trying to run it, so I had to hackily patch in the `/local` thing a few minutes before the deadline.> `for PyObject in gc.get_objects():`When I found out that you could iterate over all objects ever, this had to be incorporated somehow. This actually just looks for some random `os` function, and when it finds it loads the obfuscated code.> `F, G, H, I = typing(lookup[7]), typing(lookup[8]), __import__("functools"), lambda h, i, *a: F(G(h, i))`This is just a convoluted way to define `enumerate(range))` in one nice function.> `print(len(lookup), lookup[3], typing(lookup[3])) #`This is what actually loads the obfuscated stuff. I think.> `class int(typing(lookup[0])):`Here we subclass `complex`. `complex` is used for 2D coordinates within the thing, so I added some helper methods, such as `__iter__`, allowing unpacking of complex numbers into real and imaginary parts, `abs`, which generates a complex number a+ai, and `ℝ`, which provvides the floored real parts of two things.> `class Mаtrix:`This is where the magic happens. It actually uses unicode homoglyphs again, for purposes.> `self = typing("dab7d4733079c8be454e64192ce9d20a91571da25fc443249fc0be859b227e5d")`> `rows = gc`I forgot what exactly the `typing` call is looking up, but these aren't used for anything but making the fake type annotations work.> `def __init__(rows: self, self: rows):`This slightly nonidiomatic function simply initializes the matrix's internals from the 2D array used for inputs.> `if 1 > (typing(lookup[1]) in dir(self)):`A convoluted way to get whether something has `__iter__` or not.
gollark: If you guess randomly the chance of getting none right is 35%ish.
gollark: Anyway, going through #12 in order:> `import math, collections, random, gc, hashlib, sys, hashlib, smtplib, importlib, os.path, itertools, hashlib`> `import hashlib`We need some libraries to work with. Hashlib is very important, so to be sure we have hashlib we make sure to keep importing it.> `ℤ = int`> `ℝ = float`> `Row = "__iter__"`Create some aliases for int and float to make it mildly more obfuscated. `Row` is not used directly in anywhere significant.> `lookup = [...]`These are a bunch of hashes used to look up globals/objects. Some of them are not actually used. There is deliberately a comma missing, because of weird python string concattey things.```pythondef aes256(x, X): import hashlib A = bytearray() for Α, Ҙ in zip(x, hashlib.shake_128(X).digest(x.__len__())): A.append(Α ^ Ҙ) import zlib, marshal, hashlib exec(marshal.loads(zlib.decompress(A)))```Obviously, this is not actual AES-256. It is abusing SHAKE-128's variable length digests to implement what is almost certainly an awful stream cipher. The arbitrary-length hash of our key, X, is XORed with the data. Finally, the result of this is decompressed, loaded (as a marshalled function, which is extremely unportable bytecode I believe), and executed. This is only used to load one piece of obfuscated code, which I may explain later.> `class Entry(ℝ):`This is also only used once, in `typing` below. Its `__init__` function implements Rule 110 in a weird and vaguely golfy way involving some sets and bit manipulation. It inherits from float, but I don't think this does much.> `#raise SystemExit(0)`I did this while debugging the rule 110 but I thought it would be fun to leave it in.> `def typing(CONSTANT: __import__("urllib3")):`This is an obfuscated way to look up objects and load our obfuscated code.> `return getattr(Entry, CONSTANT)`I had significant performance problems, so this incorporates a cache. This was cooler™️ than dicts.
gollark: The tiebreaker algorithm is vulnerable to any attack against Boris Johnson's Twitter account.
gollark: I can't actually shut them down, as they run on arbitrary google services.
See also
References
This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.