Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • mfb23137/cs101-csai
  • gvb23154/cs101-csai
  • kkb23140/cs-101-cognitive-science-and-artificial-intelligence-sem-2-first-half
  • kxb23169/cs101-csai
  • xgb21195/cs101-csai
5 results
Show changes
Commits on Source (10)
...@@ -16,17 +16,21 @@ ...@@ -16,17 +16,21 @@
## Marking Scheme ## Marking Scheme
*Final due date for all assignments: 26 February*
- 10% :: Participation - 10% :: Participation
- 30% :: Assignment 1 - [Yak Shaving](./cs101-csai-lec1.pdf) - 30% :: Assignment 1 - [Yak Shaving](./cs101-csai-lec1.pdf)
- 20% :: Create a git repository with a file, and share it - 20% :: Create a git repository with a file, and share it
- 10% :: Put a transcript of a session with the Emacs doctor in that file - 10% :: Put a transcript of a session with the Emacs doctor in that file
- 30% :: Assignment 2 - [Probability and Text](./cs101-csai-lec1.pdf) - 30% :: Assignment 2 - [Probability and Text](./cs101-csai-lec1.pdf)
- 10% :: Write a program to output random characters - 10% :: Write a program to output random characters
- 10% :: Write a program that, given a character, predicts the next character - 10% :: Write a program that, given a character, predicts the next character
- 10% :: Write a program to output a sequence of characters - 10% :: Write a program to output a sequence of characters
- 10% (bonus) :: Write a program that outputs a sequence of - 10% (bonus) :: Write a program that outputs a sequence of characters conditional on the previous two characters
characters conditional on the previous two characters - 30% :: Assignment 3 - [Stochastic Parrot](./cs101-csai-assignment3.md)
- 30% :: Assignment 3 - 10% :: Write a program to output random words
- 10% :: Write a program that, given a word, predicts the next word
- 10% :: Write a program to output a sequence of words
## Topics ## Topics
...@@ -41,4 +45,4 @@ characters conditional on the previous two characters ...@@ -41,4 +45,4 @@ characters conditional on the previous two characters
[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/r54u4z_qay0/0.jpg)](https://www.youtube.com/watch?v=r54u4z_qay0) [![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/r54u4z_qay0/0.jpg)](https://www.youtube.com/watch?v=r54u4z_qay0)
More Coming! [Setting up Python - Write-Up](https://gitlab.cis.strath.ac.uk/xgb21195/cs101-csai/-/blob/main/setup.md?ref_type=heads)
# CS101/3 - CS/AI Assignment 3 - The Stochastic Parrot
Assignment 3 is just like Assignment 2 but with words instead of letters.
You may wish to use the Python NLTK (https://www.nltk.org) Natural Language
Toolkit to help break the text up into tokens (words)
You may adapt the helper functions from Assignment 2 to work with words
rather than letters or you may write your own from scratch
Optionally, instead of doing this programming exercise, you may write a
short essay, no longer than 2000 words on one of the topics that we have
touched on in the philosophy of mind:
- Turing's Imitation Game
- Dneprov's Game (or, equivalently, Searle's Chinese Room)
- Logical Behaviorism or Functionalism
- The Engineering End-Run
Assignment 3 is worth 30% in total.
## 3a word probabilities - 10%
Given an input text, compute the word probabilities and generate a word,
xgb21195@cafe:~$ ./assignment-3a example.txt
the
## 3b conditional word probabilities - 10%
Given an input text and a word, generate the next word according to the
conditional probabilities in the text,
xgb21195@cafe:~$ ./assignment-3b example.txt the
cat
## 3c a stochastic parrot - 10%
Given an input text, generate a sentence of a particular length according
to the conditional word distributions,
xgb21195@cafe:~$ ./assignment-3b example.txt 10
the cat ate a burrito that is not a butterfly
...@@ -7,14 +7,15 @@ def file2prob(filename): ...@@ -7,14 +7,15 @@ def file2prob(filename):
Read a file and return a dictionary of letters and Read a file and return a dictionary of letters and
their probabilities their probabilities
""" """
letter_dict = { c: 0 for c in letters } letter_dict = {}
letter_total = 0 letter_total = 0
with open(filename, encoding="utf-8") as fp: with open(filename, encoding="utf-8") as fp:
for c in fp.read(): for c in fp.read():
if c.lower() not in letter_dict: if c.lower() not in letters:
continue continue
letter_dict[c.lower()] += 1 c = c.lower()
letter_dict[c] = letter_dict.get(c, 0) + 1
letter_total += 1 letter_total += 1
probs = { c: letter_dict[c]/letter_total for c in letter_dict } probs = { c: letter_dict[c]/letter_total for c in letter_dict }
...@@ -27,22 +28,23 @@ def file2pairs(filename): ...@@ -27,22 +28,23 @@ def file2pairs(filename):
conditional probability of a letter given its conditional probability of a letter given its
predecessor. predecessor.
""" """
letter_dict = { c: { a: 0 for a in letters } letter_dict = {}
for c in letters }
previous = None previous = None
with open(filename, encdoing="utf-8") as fp: with open(filename, encoding="utf-8") as fp:
for c in fp.read(): for c in fp.read():
if c not in letter_dict:
continue
c = c.lower() c = c.lower()
if c not in letters:
continue
if previous is None: if previous is None:
previous = c previous = c
continue continue
letter_dict[previous][c] += 1 d = letter_dict.setdefault(previous, {})
d[c] = d.get(c, 0) + 1
previous = c previous = c
probs = { c: { d: letter_dict[c][d]/sum(letter_dict[c].values()) probs = { c: { d: letter_dict[c][d]/sum(letter_dict[c].values())
for d in letters } for c in letters } for d in letter_dict[c] } for c in letter_dict }
return probs return probs
if __name__ == '__main__': if __name__ == '__main__':
......
aabbcc
abcd
abcda
Governments of the Industrial World, you weary giants of flesh and steel, I come from Cyberspace, the new home of Mind. On behalf of the future, I ask you of the past to leave us alone. You are not welcome among us. You have no sovereignty where we gather.
We have no elected government, nor are we likely to have one, so I address you with no greater authority than that with which liberty itself always speaks. I declare the global social space we are building to be naturally independent of the tyrannies you seek to impose on us. You have no moral right to rule us nor do you possess any methods of enforcement we have true reason to fear.
Governments derive their just powers from the consent of the governed. You have neither solicited nor received ours. We did not invite you. You do not know us, nor do you know our world. Cyberspace does not lie within your borders. Do not think that you can build it, as though it were a public construction project. You cannot. It is an act of nature and it grows itself through our collective actions.
You have not engaged in our great and gathering conversation, nor did you create the wealth of our marketplaces. You do not know our culture, our ethics, or the unwritten codes that already provide our society more order than could be obtained by any of your impositions.
You claim there are problems among us that you need to solve. You use this claim as an excuse to invade our precincts. Many of these problems don't exist. Where there are real conflicts, where there are wrongs, we will identify them and address them by our means. We are forming our own Social Contract. This governance will arise according to the conditions of our world, not yours. Our world is different.
Cyberspace consists of transactions, relationships, and thought itself, arrayed like a standing wave in the web of our communications. Ours is a world that is both everywhere and nowhere, but it is not where bodies live.
We are creating a world that all may enter without privilege or prejudice accorded by race, economic power, military force, or station of birth.
We are creating a world where anyone, anywhere may express his or her beliefs, no matter how singular, without fear of being coerced into silence or conformity.
Your legal concepts of property, expression, identity, movement, and context do not apply to us. They are all based on matter, and there is no matter here.
Our identities have no bodies, so, unlike you, we cannot obtain order by physical coercion. We believe that from ethics, enlightened self-interest, and the commonweal, our governance will emerge. Our identities may be distributed across many of your jurisdictions. The only law that all our constituent cultures would generally recognize is the Golden Rule. We hope we will be able to build our particular solutions on that basis. But we cannot accept the solutions you are attempting to impose.
In the United States, you have today created a law, the Telecommunications Reform Act, which repudiates your own Constitution and insults the dreams of Jefferson, Washington, Mill, Madison, DeToqueville, and Brandeis. These dreams must now be born anew in us.
You are terrified of your own children, since they are natives in a world where you will always be immigrants. Because you fear them, you entrust your bureaucracies with the parental responsibilities you are too cowardly to confront yourselves. In our world, all the sentiments and expressions of humanity, from the debasing to the angelic, are parts of a seamless whole, the global conversation of bits. We cannot separate the air that chokes from the air upon which wings beat.
In China, Germany, France, Russia, Singapore, Italy and the United States, you are trying to ward off the virus of liberty by erecting guard posts at the frontiers of Cyberspace. These may keep out the contagion for a small time, but they will not work in a world that will soon be blanketed in bit-bearing media.
Your increasingly obsolete information industries would perpetuate themselves by proposing laws, in America and elsewhere, that claim to own speech itself throughout the world. These laws would declare ideas to be another industrial product, no more noble than pig iron. In our world, whatever the human mind may create can be reproduced and distributed infinitely at no cost. The global conveyance of thought no longer requires your factories to accomplish.
These increasingly hostile and colonial measures place us in the same position as those previous lovers of freedom and self-determination who had to reject the authorities of distant, uninformed powers. We must declare our virtual selves immune to your sovereignty, even as we continue to consent to your rule over our bodies. We will spread ourselves across the Planet so that no one can arrest our thoughts.
We will create a civilization of the Mind in Cyberspace. May it be more humane and fair than the world your governments have made before.
../lec2
\ No newline at end of file
#!/bin/bash
CS=/home/xgb21195/teaching/cs101
TOK=`cat ~/.gitlab`
mark1 () {
date 1>&2
echo "Marking Assignment 1 for ${dsname}" 1>&2
echo "Marking Assignment 1"; echo
marks=0
nfiles=`find . -type f | sed '/^\.\/\./d' | wc -l`
find . -type f | sed '/^\.\/\./d' | while read f; do
touch ${marking}/assignment-1.files
if grep -q 'I am the psychotherapist. Please, describe your problems.' "$f"; then
touch ${marking}/assignment-1.emacs
fi
done
if test -f ${marking}/assignment-1.files; then
echo " Found some files... 20/20 marks"
marks=20
else
echo " Found no files... 0/20 marks"
fi
if test -f ${marking}/assignment-1.emacs; then
echo " Found an interaction with the Emacs doctor... 10/10 marks"
marks=$(($marks + 10))
else
echo " Found no interaction with the Emacs doctor... 0/10 marks"
fi
echo
echo "${marks}/30 marks in total"
echo "${marks} marks" 1>&2
}
dsname="$1"
student="${CS}/students/${dsname}"
marking="${CS}/marking/${dsname}"
mark1
from multiprocessing import Pool
from scipy.stats import wasserstein_distance as emd
from Levenshtein import distance as levenshtein
from sys import argv
from sys import stdout
from lec2.letters import file2prob, letters
from random import choices, sample
from subprocess import PIPE, DEVNULL, STDOUT
import subprocess
import ast
import os
import re
CS="/home/xgb21195/teaching/cs101"
republic = "/home/xgb21195/teaching/cs101/cs101-csai/lec2/republic.txt"
modest = "/home/xgb21195/teaching/cs101/cs101-csai/marking/modest.txt"
aabbcc = "/home/xgb21195/teaching/cs101/cs101-csai/marking/aabbcc.txt"
sbre = re.compile("^ *\['([a-z ])'\].*|.*: ([a-z ])$")
def ngrams(data, n=2):
"""
From the data, construct a dictionary of n-grams and
the probabilities of following letters. That is, the
conditional probability of a letter given its n
"""
letter_dict = {}
previous = []
for c in data:
c = c.lower()
if c not in letters:
continue
if len(previous) == n:
key = "".join(previous)
counts = letter_dict.setdefault(key, {})
counts[c] = counts.get(c, 0) + 1
letter_dict[key][c] += 1
previous.append(c)
previous = previous[-n:]
probs = { c: { d: letter_dict[c][d]/sum(letter_dict[c].values())
for d in letter_dict[c].keys() } for c in letter_dict.keys() }
return probs
def file2ngrams(filename, n=2):
"""
Read a file and return a dictionary of n-grams and
the probabilities of following letters. That is, the
conditional probability of a letter given its n
predecessors.
"""
with open(filename, encoding="utf-8") as fp:
return ngrams(fp.read(), n)
def find_assignment(repo, name):
for d, subs, files in os.walk(repo, name):
for fname in files:
lname = fname.lower()
if lname.startswith("assignment") and name in lname:
return os.path.join(repo, d, fname)
def ispython(fname):
try:
with open(fname) as fp:
p = fp.read()
ast.parse(p)
return True
except:
return False
def runner(fname):
if ispython(fname):
def _run(*args):
cmd = ["/bin/python", fname] + [str(a) for a in args]
try:
proc = subprocess.run(cmd, timeout=15, stdin=DEVNULL, stdout=PIPE, stderr=STDOUT)
if proc.returncode is not None and proc.returncode != 0:
return None
return proc.stdout.decode("utf-8")
except Exception as e:
print(f"Error running program: {e}")
return None
else:
def _run(*args):
cmd = [fname] + [str(a) for a in args]
try:
proc = subprocess.run(cmd, timeout=15, stdin=DEVNULL, stdout=PIPE, stderr=STDOUT)
if proc.returncode is not None and proc.returncode != 0:
return None
return proc.stdout.decode("utf-8")
except Exception as e:
print(f"Error running program: {e}")
return None
return _run
def run(args):
fname = args[0]
_run = runner(fname)
result = _run(*args[1:])
return result.rstrip("\r\n") if result is not None else None
def pmark(indent, msg, marks):
l = indent*4 + len(msg)
dent = ' ' * (indent*4)
dots = '.' * (69-l)
print(dent + msg + dots + " " + marks + " marks")
def mark2a(repo):
tally = 0
stdout.write("Finding assignment 2a...")
prog = find_assignment(repo, "2a")
if prog is None:
print(" not found")
pmark(1, "Could not find assignment 2a", "0/10")
return 0
print(f" {prog}")
output = run((prog, aabbcc))
if output is None:
pmark(1, "Program cannot be run", "0/10")
return 0
else:
pmark(1, "Program exists and can be run", "1/1")
tally += 1
output = output.strip()
if len(output) == 1 and output in "abc":
pmark(1, "Program output is well-formed", "2/2")
tally += 2
else:
pmark(1, "Program output is not well-formed", "0/2")
print(" Expected a single letter, either 'a', 'b', or 'c', got:")
print(f" {repr(output)}")
print(" Will try to compensate for this for the rest of 2a")
print(" Testing AABBCC distribution...")
counts = {}
with Pool(processes=4) as pool:
for c in pool.imap_unordered(run, [(prog, aabbcc) for _ in range(2500)]):
if c is None:
continue
if len(c) != 1:
m = sbre.match(c)
if m is None:
continue
bra, end = m.groups()
if bra is not None: c = bra
else: c = end
counts[c] = counts.get(c, 0) + 1
probs = { c : counts[c]/sum(counts.values()) for c in counts }
n = len(probs)
if n != 3:
pmark(2, f"Strange distribution of size {n} found", "0/2")
else:
pmark(2, f"Ternary distribution found", "1/1")
tally += 1
balanced = all( abs(0.3333-v) < 0.03 for v in probs.values() )
if balanced:
pmark(2, "Balanced ternary distribution found", "1/1")
tally += 1
else:
pmark(2, "Unbalanced ternary distribution found", "0/1")
print(f" {probs}")
modest_probs = file2prob(modest)
print(" Testing A Modest Proposal...")
counts = {}
with Pool(processes=24) as pool:
for c in pool.imap_unordered(run, [(prog, modest) for _ in range(2500)]):
if c is None:
continue
if len(c) != 1:
m = sbre.match(c)
if m is None:
continue
bra, end = m.groups()
if bra is not None: c = bra
else: c = end
counts[c] = counts.get(c, 0) + 1
probs = { c : counts[c]/sum(counts.values()) for c in counts }
if len(probs) > 0:
exp_support = sorted(list(modest_probs.keys()))
ans_support = sorted(list(probs.keys()))
d = levenshtein("".join(exp_support), "".join(ans_support))
if d > 2:
pmark(2, f"Distribution with bad support (d={d}) found", "0/2")
print(f" Exp: {exp_support}")
print(f" Got: {ans_support}")
else:
pmark(2, f"Distribution with acceptable support (d={d}) found", "2/2")
tally += 2
u = list(modest_probs.values())
v = list(probs.values())
d = emd(u, v)
df = "%.04f" % d
if d < 0.01:
pmark(2, f"Distribution acceptably close (d={df})", "3/3")
tally += 3
else:
pmark(2, f"Distribution too far away (d={df})", "0/3")
else:
pmark(2, "Could not understand program output", "0/5")
return tally
def mark2b(repo):
tally = 0
stdout.write("Finding assignment 2b...")
prog = find_assignment(repo, "2b")
if prog is None:
print(" not found")
pmark(1, "Could not find assignment 2b", "0/10")
return 0
print(f" {prog}")
# prog = "../assignment-2b.py"
pairs = file2ngrams(modest, 1)
probs = file2prob(modest)
support = [k for k in probs.keys() if k != ' ']
distrib = [probs[k] for k in support]
output = run((prog, modest, "e"))
if output is not None:
pmark(1, "Program exists and can be run", "2/2")
tally += 2
if output in letters:
pmark(1, "Output is well-formed", "2/2")
tally += 2
else:
pmark(1, "Output is not well-formed", "0/2")
else:
pmark(1, "Program cannot be run", "0/10")
return 0
for init in sample(support, 2, counts=[int(1000*p) for p in distrib]):
stdout.write(f" Computing 2-gram distribution starting with {init}......")
counts = {}
with Pool(processes=24) as pool:
for c in pool.imap_unordered(run, [(prog, modest, init) for _ in range(2500)]):
if c is None or len(c) != 1:
continue
counts[c] = counts.get(c, 0) + 1
print(" done.")
if len(counts) == 0:
pmark(2, "Bad program output", "0/2")
continue
probs = { c : counts[c]/sum(counts.values()) for c in counts }
exp_support = sorted(list(pairs[init].keys()))
exp_distrib = [pairs[init][k] for k in exp_support]
ans_support = sorted(list(probs.keys()))
ans_distrib = [probs[k] for k in ans_support]
d = levenshtein("".join(exp_support), "".join(ans_support))
if d < 4:
pmark(2, f"Support is good (d={d})", "1/1")
tally += 1
else:
pmark(2, f"Support is not good (d={d})", "0/1")
print(f" Exp {exp_support}")
print(f" Got {ans_support}")
d = emd(exp_distrib, ans_distrib)
df = "%.04f" % d
if d < 0.01:
pmark(2, f"Distribution is acceptably close (d={df})", "1/1")
tally += 1
else:
pmark(2, f"Distribution is too far (d={df})", "0/1")
proc = subprocess.run(["/bin/python", prog, "abcd.txt", "d"], timeout=10, stdin=DEVNULL, stdout=PIPE, stderr=STDOUT)
if proc.returncode is not None:
pmark(1, f"Correct error on sneaky test case", "2/2")
tally += 2
else:
print(1, f"Sneaky test case does not error", "0/2")
return tally
def mark2c(repo):
tally = 0
stdout.write("Finding assignment 2c...")
prog = find_assignment(repo, "2c")
if prog is None:
print(" not found")
pmark(1, "Could not find assignment 2c", "0/10")
return 0
print(f" {prog}")
return mark_ngrams(prog, 1)
def mark2d(repo):
tally = 0
stdout.write("Finding assignment 2d (bonus)...")
prog = find_assignment(repo, "2d")
if prog is None:
print(" not found")
pmark(1, "Could not find assignment 2d", "0/10")
return 0
print(f" {prog}")
return mark_ngrams(prog, 2)
def mark_ngrams(prog, n):
output = run((prog, modest, 100000))
if output is None:
pmark(1, f"Could not run program", "0/10")
return 0
output = output.strip()
exp = file2ngrams(modest, n)
ans = ngrams(output, n)
tally = 0
output = run((prog, modest, "100"))
if output is not None:
pmark(1, "Program exists and can be run", "2/2")
tally += 2
if len(output) == 100:
pmark(1, "Output is well-formed", "2/2")
tally += 2
else:
pmark(1, "Output is not well-formed", "0/8")
return tally
else:
pmark(1, "Program cannot be run", "0/10")
return tally
for gram in sample(list(exp.keys()), 3):
print(f" Comparing distributions for {n+1}-grams starting with {gram}")
if gram not in ans:
pmark(2, f"{n}-gram '{gram}' not found in answer", "0/2")
continue
exp_cond = exp[gram]
ans_cond = ans[gram]
exp_support = sorted(list(exp[gram].keys()))
ans_support = sorted(list(ans[gram].keys()))
d = levenshtein("".join(exp_support), "".join(ans_support))
if d < 4:
pmark(2, f"Support is good (d={d})", "1/1")
tally += 1
else:
pmark(2, f"Support is not good (d={d})", "0/1")
print(f" Exp {exp_support}")
print(f" Got {ans_support}")
exp_distrib = [exp[gram][k] for k in exp_support]
ans_distrib = [ans[gram][k] for k in ans_support]
d = emd(exp_distrib, ans_distrib)
df = "%.04f" % d
if d < 0.01:
pmark(2, f"Distribution is acceptably close (d={df})", "1/1")
tally += 1
else:
pmark(2, f"Distribution is too far (d={df})", "0/1")
return tally
def mkseed(s):
x = 0
for c in s:
x ^= ord(c)
return x
if __name__ == '__main__':
from random import seed
dsname=argv[1]
marks = os.path.join(CS, "marking", dsname)
repo = os.path.join(CS, "repos", dsname)
tally = 0
bonus = 0
print("Marking Assignment 2")
print("====================")
print()
seed(mkseed(dsname))
tally += mark2a(repo)
tally += mark2b(repo)
tally += mark2c(repo)
bonus += mark2d(repo)
print("="*80)
pmark(0, "Total for assignment 2", f"{tally+bonus}/30")
from multiprocessing import Pool
from string import ascii_letters, digits
from scipy.stats import wasserstein_distance as emd
from Levenshtein import distance as levenshtein
from sys import argv
from sys import stdout
from random import choices, sample
from subprocess import PIPE, DEVNULL, STDOUT
from nltk.tokenize import word_tokenize
import subprocess
import ast
import os
import re
CS="/home/xgb21195/teaching/cs101"
republic = "/home/xgb21195/teaching/cs101/cs101-csai/lec2/republic.txt"
barlow = "/home/xgb21195/teaching/cs101/cs101-csai/marking/barlow.txt"
with open(barlow) as fp:
barlow_words = [w.lower() for w in word_tokenize(fp.read())]
aabbcc = "/home/xgb21195/teaching/cs101/cs101-csai/marking/aabbcc.txt"
mary = "/home/xgb21195/teaching/cs101/cs101-csai/marking/mary.txt"
with open(mary) as fp:
mary_words = [w.lower() for w in word_tokenize(fp.read())]
nltkvomit = '[nltk_data] Downloading package punkt to /home/xgb21195/nltk_data...\n[nltk_data] Package punkt is already up-to-date!\n'
letters = ascii_letters + digits
def ntoks(data, n=2):
"""
From the data, construct a dictionary of n-tokens and
the probabilities of following words. That is, the
conditional probability of a word given its n predecessors
"""
word_dict = {}
previous = []
for w in word_tokenize(data):
w = w.lower()
if len(previous) == n:
key = tuple(previous)
counts = word_dict.setdefault(key, {})
counts[w] = counts.get(w, 0) + 1
word_dict[key][w] += 1
previous.append(w)
previous = previous[-n:]
probs = { c: { d: word_dict[c][d]/sum(word_dict[c].values())
for d in word_dict[c].keys() } for c in word_dict.keys() }
return probs
def file2ntoks(filename, n=2):
"""
Read a file and return a dictionary of n-toks and
the probabilities of following words. That is, the
conditional probability of a word given its n
predecessors.
"""
with open(filename, encoding="utf-8") as fp:
return ntoks(fp.read(), n)
def file2prob(filename):
"""
Read a file and return a dictionary of letters and
their probabilities
"""
word_dict = {}
word_total = 0
with open(filename, encoding="utf-8") as fp:
for w in word_tokenize(fp.read()):
w = w.lower()
word_dict[w] = word_dict.get(w, 0) + 1
word_total += 1
probs = { w: word_dict[w]/word_total for w in word_dict }
return probs
def find_assignment(repo, name):
for d, subs, files in os.walk(repo, name):
for fname in files:
lname = fname.lower()
if lname.startswith("assignment") and name in lname:
return os.path.join(repo, d, fname)
def ispython(fname):
try:
with open(fname) as fp:
p = fp.read()
ast.parse(p)
return True
except:
return False
def runner(fname):
if ispython(fname):
def _run(*args):
cmd = ["/bin/python", fname] + [str(a) for a in args]
try:
proc = subprocess.run(cmd, timeout=15, stdin=DEVNULL, stdout=PIPE, stderr=STDOUT)
if proc.returncode is not None and proc.returncode != 0:
return None
return proc.stdout.decode("utf-8")
except Exception as e:
print(f"Error running program: {e}")
return None
else:
def _run(*args):
cmd = [fname] + [str(a) for a in args]
try:
proc = subprocess.run(cmd, timeout=15, stdin=DEVNULL, stdout=PIPE, stderr=STDOUT)
if proc.returncode is not None and proc.returncode != 0:
return None
return proc.stdout.decode("utf-8")
except Exception as e:
print(f"Error running program: {e}")
return None
return _run
def run(args):
fname = args[0]
_run = runner(fname)
result = _run(*args[1:])
return result.removeprefix(nltkvomit).rstrip("\r\n") if result is not None else None
def pmark(indent, msg, marks):
l = indent*4 + len(msg)
dent = ' ' * (indent*4)
dots = '.' * (69-l)
print(dent + msg + dots + " " + marks + " marks")
def mark3a(repo):
tally = 0
stdout.write("Finding assignment 3a...")
prog = find_assignment(repo, "3a")
if prog is None:
print(" not found")
pmark(1, "Could not find assignment 3a", "0/10")
return 0
print(f" {prog}")
output = run((prog, mary))
if output is None:
pmark(1, "Program cannot be run", "0/10")
print(" " + " ".join((prog, mary)))
return 0
else:
pmark(1, "Program exists and can be run", "1/1")
tally += 1
output = output.strip().removeprefix(nltkvomit)
if output in mary_words:
pmark(1, "Program output is well-formed", "2/2")
tally += 2
else:
pmark(1, "Program output is not well-formed", "0/2")
print(f" Expected a single word in {mary_words}, got:")
print(f" {repr(output)}"[:500] + "...")
print(" Testing mary.txt distribution...")
counts = {}
with Pool(processes=6) as pool:
for w in pool.imap_unordered(run, [(prog, mary) for _ in range(360)]):
if w is None:
continue
counts[w] = counts.get(w, 0) + 1
probs = { w : counts[w]/sum(counts.values()) for w in counts }
n = len(probs)
if n != 5:
pmark(2, f"Strange distribution of size {n} found", "0/2")
else:
pmark(2, f"5-ary distribution found", "1/1")
tally += 1
balanced = all( abs(0.2-v) < 0.05 for v in probs.values() )
if balanced:
pmark(2, "Balanced 5-ary distribution found", "1/1")
tally += 1
else:
pmark(2, "Unbalanced 5-ary distribution found", "0/1")
print(f" {probs}")
barlow_probs = file2prob(barlow)
print(" Testing barlow.txt...")
counts = {}
with Pool(processes=6) as pool:
for w in pool.imap_unordered(run, [(prog, barlow) for _ in range(360)]):
if w is None:
continue
counts[w] = counts.get(w, 0) + 1
probs = { w : counts[w]/sum(counts.values()) for w in counts }
if len(probs) > 0:
exp_support = sorted(list(barlow_probs.keys()))
ans_support = sorted(list(k.lower() for k in probs.keys()))
d = levenshtein(" ".join(exp_support), " ".join(ans_support))
if d > 50:
pmark(2, f"Distribution with bad support (d={d}) found", "0/2")
print(f" Exp: {exp_support}"[:500] + "...")
print(f" Got: {ans_support}"[:500] + "...")
else:
pmark(2, f"Distribution with acceptable support (d={d}) found", "2/2")
tally += 2
u = list(barlow_probs.values())
v = list(probs.values())
d = emd(u, v)
df = "%.04f" % d
if d < 0.01:
pmark(2, f"Distribution acceptably close (d={df})", "3/3")
tally += 3
else:
pmark(2, f"Distribution too far away (d={df})", "0/3")
else:
pmark(2, "Could not understand program output", "0/5")
return tally
def mark3b(repo):
tally = 0
stdout.write("Finding assignment 3b...")
prog = find_assignment(repo, "3b")
if prog is None:
print(" not found")
pmark(1, "Could not find assignment 3b", "0/10")
return 0
print(f" {prog}")
all_pairs = file2ntoks(barlow, 1)
probs = file2prob(barlow)
support = [k for k in probs.keys()]
distrib = [probs[k] for k in support]
output = run((prog, barlow, "it"))
if output is not None:
pmark(1, "Program exists and can be run", "2/2")
tally += 2
if output in barlow_words:
pmark(1, "Output is well-formed", "2/2")
tally += 2
else:
pmark(1, "Output is not well-formed", "0/2")
print(f" Expected one of JPB's words, got {output[:100]}...")
else:
pmark(1, "Program cannot be run", "0/10")
print(" " + " ".join((prog, barlow, "it")))
return 0
# it was unclear in the instructions whether punctuation
# should be included. NLTK's word_tokenize() thinks that
# punctuation symbols are words. if the student does not
# include punctuation, drop it from our reference
# distribution
def filter(d):
return { k: desc(w) for k,w in d.items()
if all(c in letters for c in k[0]) }
def desc(v):
return filter(v) if isinstance(v, dict) else v
def renorm(d):
return { k: v/sum(d.values()) for k, v in d.items() }
words = filter(probs)
for init in sample(list(words.keys()), 2, counts=[int(1000*p) for p in words.values()]):
stdout.write(f" Computing 2-token distribution starting with '{init}'......")
counts = {}
with Pool(processes=6) as pool:
for w in pool.imap_unordered(run, [(prog, barlow, init) for _ in range(120)]):
if w is None:
continue
w = w.lower()
counts[w] = counts.get(w, 0) + 1
print(" done.")
if len(counts) == 0:
pmark(2, "Bad program output", "0/2")
continue
probs = { w : counts[w]/sum(counts.values()) for w in counts }
if all(all(c in letters for c in w) for w in probs):
print(" No punctuation found at top level, renormalising.")
pairs = { k: renorm(v) for k, v in filter(all_pairs).items() }
else:
pairs = all_pairs
exp_support = sorted(list(pairs[(init,)].keys()))
exp_distrib = [pairs[(init,)][k] for k in exp_support]
exp_string = " ".join(t[0] for t in exp_support)
ans_support = sorted(list(probs.keys()))
ans_distrib = [probs[k] for k in ans_support]
ans_string = " ".join(ans_support)
if len(exp_support) == 0:
if len(ans_support) == 0:
pmark(2, f"Correctly returned an empty distribution", "2/2")
else:
pmark(2, f"Invalid distribution size {len(ans_support)} should be {len(exp_support)}", "0/2")
else:
d = levenshtein(exp_string, ans_string)
if d < 200:
pmark(2, f"Support is good (d={d})", "1/1")
tally += 1
else:
pmark(2, f"Support is not good (d={d})", "0/1")
print(f" Exp {exp_support}"[:500] + "...")
print(f" Got {ans_support}"[:500] + "...")
if len(ans_distrib) > 0:
d = emd(exp_distrib, ans_distrib)
df = "%.04f" % d
if d < 0.1:
pmark(2, f"Distribution is acceptably close (d={df})", "1/1")
tally += 1
else:
pmark(2, f"Distribution is too far (d={df})", "0/1")
print(f" Exp {exp_support}"[:500] + "...")
print(f" {exp_distrib}"[:500] + "...")
print(f" Got {ans_support}"[:500] + "...")
print(f" {ans_distrib}"[:500] + "...")
else:
pmark(2, "Distribution is empty", "0/1")
proc = subprocess.run(["/bin/python", prog, mary, "lamb"], timeout=10, stdin=DEVNULL, stdout=PIPE, stderr=STDOUT)
if proc.returncode is not None:
pmark(1, f"Correct error on sneaky test case", "2/2")
tally += 2
else:
print(1, f"Sneaky test case does not error", "0/2")
return tally
def mark3c(repo):
tally = 0
stdout.write("Finding assignment 3c...")
prog = find_assignment(repo, "3c")
if prog is None:
print(" not found")
pmark(1, "Could not find assignment 3c", "0/10")
return 0
print(f" {prog}")
return mark_toks(prog, 1)
def mark3d(repo):
tally = 0
stdout.write("Finding assignment 3d (bonus)...")
prog = find_assignment(repo, "3d")
if prog is None:
print(" not found")
pmark(1, "Could not find assignment 3d", "0/10")
return 0
print(f" {prog}")
return mark_toks(prog, 2)
def mark_toks(prog, n):
output = run((prog, barlow, 100))
if output is None:
pmark(1, f"Could not run program", "0/10")
print(" " + " ".join((prog, barlow, "100")))
return 0
exp = file2ntoks(barlow, n)
tally = 0
output = []
with Pool(processes=6) as pool:
for s in pool.imap_unordered(run, [(prog, barlow, 100) for _ in range(24)]):
if s is None:
continue
output.append(s.strip())
if len(output) > 0:
pmark(1, "Program exists and can be run", "2/2")
tally += 2
sentence = " ".join(output)
words = word_tokenize(sentence)
ans = ntoks(sentence, n)
nwords = len(words)
if nwords == 2400:
pmark(1, "Output is well-formed", "2/2")
tally += 2
else:
pmark(1, f"Expected 2400 words in total, got {nwords}", "0/8")
return tally
else:
pmark(1, "Program cannot be run", "0/10")
print(" " + " ".join((prog, barlow, "it")))
return tally
for word in sample(list(exp.keys()), 3):
print(f" Comparing distributions for {n+1}-words starting with {' '.join(word)}")
if word not in ans:
pmark(2, f"{n}-word '{' '.join(word)}' not found in answer", "0/2")
print(f" answer: {list(' '.join(w) for w in ans)}")
continue
exp_cond = exp[word]
ans_cond = ans[word]
exp_support = sorted(list(exp[word].keys()))
ans_support = sorted(list(ans[word].keys()))
d = levenshtein("".join(exp_support), "".join(ans_support))
if d < 4:
pmark(2, f"Support is good (d={d})", "1/1")
tally += 1
else:
pmark(2, f"Support is not good (d={d})", "0/1")
print(f" Exp {exp_support}"[:500] + "...")
print(f" Got {ans_support}"[:500] + "...")
exp_distrib = [exp[word][k] for k in exp_support]
ans_distrib = [ans[word][k] for k in ans_support]
d = emd(exp_distrib, ans_distrib)
df = "%.04f" % d
if d < 0.1:
pmark(2, f"Distribution is acceptably close (d={df})", "1/1")
tally += 1
else:
pmark(2, f"Distribution is too far (d={df})", "0/1")
return tally
def mkseed(s):
x = 0
for c in s:
x ^= ord(c)
return x
if __name__ == '__main__':
from random import seed
dsname=argv[1]
marks = os.path.join(CS, "marking", dsname)
repo = os.path.join(CS, "repos", dsname)
tally = 0
bonus = 0
print("Marking Assignment 3")
print("====================")
print()
seed(mkseed(dsname))
tally += mark3a(repo)
tally += mark3b(repo)
tally += mark3c(repo)
print("="*80)
pmark(0, "Total for assignment 3", f"{tally}/30")
mary had a little lamb

A Modest Proposal
For preventing the children of poor people in Ireland,
from being a burden on their parents or country,
and for making them beneficial to the publick.
by Dr. Jonathan Swift
1729
It is a melancholy object to those, who walk through this great town,
or travel in the country, when they see the streets, the roads, and
cabbin-doors crowded with beggars of the female sex, followed by three,
four, or six children, all in rags, and importuning every passenger for
an alms. These mothers, instead of being able to work for their honest
livelihood, are forced to employ all their time in stroling to beg
sustenance for their helpless infants who, as they grow up, either turn
thieves for want of work, or leave their dear native country, to fight
for the Pretender in Spain, or sell themselves to the Barbadoes.
I think it is agreed by all parties, that this prodigious number of
children in the arms, or on the backs, or at the heels of their
mothers, and frequently of their fathers, is in the present deplorable
state of the kingdom, a very great additional grievance; and therefore
whoever could find out a fair, cheap and easy method of making these
children sound and useful members of the commonwealth, would deserve so
well of the publick, as to have his statue set up for a preserver of
the nation.
But my intention is very far from being confined to provide only for
the children of professed beggars: it is of a much greater extent, and
shall take in the whole number of infants at a certain age, who are
born of parents in effect as little able to support them, as those who
demand our charity in the streets.
As to my own part, having turned my thoughts for many years upon this
important subject, and maturely weighed the several schemes of our
projectors, I have always found them grossly mistaken in their
computation. It is true, a child just dropt from its dam, may be
supported by her milk, for a solar year, with little other nourishment:
at most not above the value of two shillings, which the mother may
certainly get, or the value in scraps, by her lawful occupation of
begging; and it is exactly at one year old that I propose to provide
for them in such a manner, as, instead of being a charge upon their
parents, or the parish, or wanting food and raiment for the rest of
their lives, they shall, on the contrary, contribute to the feeding,
and partly to the clothing of many thousands.
There is likewise another great advantage in my scheme, that it will
prevent those voluntary abortions, and that horrid practice of women
murdering their bastard children, alas! too frequent among us,
sacrificing the poor innocent babes, I doubt, more to avoid the expence
than the shame, which would move tears and pity in the most savage and
inhuman breast.
The number of souls in this kingdom being usually reckoned one million
and a half, of these I calculate there may be about two hundred
thousand couple, whose wives are breeders; from which number I subtract
thirty thousand couple, who are able to maintain their own children,
(although I apprehend there cannot be so many under the present
distresses of the kingdom) but this being granted, there will remain a
hundred and seventy thousand breeders. I again subtract fifty thousand,
for those women who miscarry, or whose children die by accident or
disease within the year. There only remain a hundred and twenty
thousand children of poor parents annually born. The question therefore
is, How this number shall be reared and provided for? which, as I have
already said, under the present situation of affairs, is utterly
impossible by all the methods hitherto proposed. For we can neither
employ them in handicraft or agriculture; they neither build houses, (I
mean in the country) nor cultivate land: they can very seldom pick up a
livelihood by stealing till they arrive at six years old; except where
they are of towardly parts, although I confess they learn the rudiments
much earlier; during which time they can however be properly looked
upon only as probationers; as I have been informed by a principal
gentleman in the county of Cavan, who protested to me, that he never
knew above one or two instances under the age of six, even in a part of
the kingdom so renowned for the quickest proficiency in that art.
I am assured by our merchants, that a boy or a girl, before twelve
years old, is no saleable commodity, and even when they come to this
age, they will not yield above three pounds, or three pounds and half a
crown at most, on the exchange; which cannot turn to account either to
the parents or kingdom, the charge of nutriments and rags having been
at least four times that value.
I shall now therefore humbly propose my own thoughts, which I hope will
not be liable to the least objection.
I have been assured by a very knowing American of my acquaintance in
London, that a young healthy child well nursed, is, at a year old, a
most delicious nourishing and wholesome food, whether stewed, roasted,
baked, or boiled; and I make no doubt that it will equally serve in a
fricasee, or a ragoust.
I do therefore humbly offer it to publick consideration, that of the
hundred and twenty thousand children, already computed, twenty thousand
may be reserved for breed, whereof only one fourth part to be males;
which is more than we allow to sheep, black cattle, or swine, and my
reason is, that these children are seldom the fruits of marriage, a
circumstance not much regarded by our savages, therefore, one male will
be sufficient to serve four females. That the remaining hundred
thousand may, at a year old, be offered in sale to the persons of
quality and fortune, through the kingdom, always advising the mother to
let them suck plentifully in the last month, so as to render them
plump, and fat for a good table. A child will make two dishes at an
entertainment for friends, and when the family dines alone, the fore or
hind quarter will make a reasonable dish, and seasoned with a little
pepper or salt, will be very good boiled on the fourth day, especially
in winter.
I have reckoned upon a medium, that a child just born will weigh 12
pounds, and in a solar year, if tolerably nursed, encreaseth to 28
pounds.
I grant this food will be somewhat dear, and therefore very proper for
landlords, who, as they have already devoured most of the parents, seem
to have the best title to the children.
Infant’s flesh will be in season throughout the year, but more
plentiful in March, and a little before and after; for we are told by a
grave author, an eminent French physician, that fish being a prolifick
dyet, there are more children born in Roman Catholick countries about
nine months after Lent, than at any other season; therefore, reckoning
a year after Lent, the markets will be more glutted than usual, because
the number of Popish infants, is at least three to one in this kingdom,
and therefore it will have one other collateral advantage, by lessening
the number of Papists among us.
I have already computed the charge of nursing a beggar’s child (in
which list I reckon all cottagers, labourers, and four-fifths of the
farmers) to be about two shillings per annum, rags included; and I
believe no gentleman would repine to give ten shillings for the carcass
of a good fat child, which, as I have said, will make four dishes of
excellent nutritive meat, when he hath only some particular friend, or
his own family to dine with him. Thus the squire will learn to be a
good landlord, and grow popular among his tenants, the mother will have
eight shillings neat profit, and be fit for work till she produces
another child.
Those who are more thrifty (as I must confess the times require) may
flay the carcass; the skin of which, artificially dressed, will make
admirable gloves for ladies, and summer boots for fine gentlemen.
As to our City of Dublin, shambles may be appointed for this purpose,
in the most convenient parts of it, and butchers we may be assured will
not be wanting; although I rather recommend buying the children alive,
and dressing them hot from the knife, as we do roasting pigs.
A very worthy person, a true lover of his country, and whose virtues I
highly esteem, was lately pleased in discoursing on this matter, to
offer a refinement upon my scheme. He said, that many gentlemen of this
kingdom, having of late destroyed their deer, he conceived that the
want of venison might be well supplied by the bodies of young lads and
maidens, not exceeding fourteen years of age, nor under twelve; so
great a number of both sexes in every county being now ready to starve
for want of work and service: and these to be disposed of by their
parents if alive, or otherwise by their nearest relations. But with due
deference to so excellent a friend, and so deserving a patriot, I
cannot be altogether in his sentiments; for as to the males, my
American acquaintance assured me from frequent experience, that their
flesh was generally tough and lean, like that of our schoolboys, by
continual exercise, and their taste disagreeable, and to fatten them
would not answer the charge. Then as to the females, it would, I think,
with humble submission, be a loss to the publick, because they soon
would become breeders themselves: and besides, it is not improbable
that some scrupulous people might be apt to censure such a practice,
(although indeed very unjustly) as a little bordering upon cruelty,
which, I confess, hath always been with me the strongest objection
against any project, how well soever intended.
But in order to justify my friend, he confessed, that this expedient
was put into his head by the famous Psalmanaazor, a native of the
island Formosa, who came from thence to London, above twenty years ago,
and in conversation told my friend, that in his country, when any young
person happened to be put to death, the executioner sold the carcass to
persons of quality, as a prime dainty; and that, in his time, the body
of a plump girl of fifteen, who was crucified for an attempt to poison
the Emperor, was sold to his imperial majesty’s prime minister of
state, and other great mandarins of the court in joints from the
gibbet, at four hundred crowns. Neither indeed can I deny, that if the
same use were made of several plump young girls in this town, who
without one single groat to their fortunes, cannot stir abroad without
a chair, and appear at a playhouse and assemblies in foreign fineries
which they never will pay for, the kingdom would not be the worse.
Some persons of a desponding spirit are in great concern about that
vast number of poor people, who are aged, diseased, or maimed; and I
have been desired to employ my thoughts what course may be taken, to
ease the nation of so grievous an incumbrance. But I am not in the
least pain upon that matter, because it is very well known, that they
are every day dying, and rotting, by cold and famine, and filth, and
vermin, as fast as can be reasonably expected. And as to the young
labourers, they are now in almost as hopeful a condition. They cannot
get work, and consequently pine away from want of nourishment, to a
degree, that if at any time they are accidentally hired to common
labour, they have not strength to perform it, and thus the country and
themselves are happily delivered from the evils to come.
I have too long digressed, and therefore shall return to my subject. I
think the advantages by the proposal which I have made are obvious and
many, as well as of the highest importance.
For first, as I have already observed, it would greatly lessen the
number of Papists, with whom we are yearly overrun, being the principal
breeders of the nation, as well as our most dangerous enemies, and who
stay at home on purpose with a design to deliver the kingdom to the
Pretender, hoping to take their advantage by the absence of so many
good Protestants, who have chosen rather to leave their country, than
stay at home and pay tithes against their conscience to an episcopal
curate.
Secondly, The poorer tenants will have something valuable of their own,
which by law may be made liable to a distress, and help to pay their
landlord’s rent, their corn and cattle being already seized, and money
a thing unknown.
Thirdly, Whereas the maintainance of a hundred thousand children, from
two years old, and upwards, cannot be computed at less than ten
shillings a piece per annum, the nation’s stock will be thereby
encreased fifty thousand pounds per annum, besides the profit of a new
dish, introduced to the tables of all gentlemen of fortune in the
kingdom, who have any refinement in taste. And the money will circulate
among our selves, the goods being entirely of our own growth and
manufacture.
Fourthly, The constant breeders, besides the gain of eight shillings
sterling per annum by the sale of their children, will be rid of the
charge of maintaining them after the first year.
Fifthly, This food would likewise bring great custom to taverns, where
the vintners will certainly be so prudent as to procure the best
receipts for dressing it to perfection; and consequently have their
houses frequented by all the fine gentlemen, who justly value
themselves upon their knowledge in good eating; and a skilful cook, who
understands how to oblige his guests, will contrive to make it as
expensive as they please.
Sixthly, This would be a great inducement to marriage, which all wise
nations have either encouraged by rewards, or enforced by laws and
penalties. It would encrease the care and tenderness of mothers towards
their children, when they were sure of a settlement for life to the
poor babes, provided in some sort by the publick, to their annual
profit instead of expence. We should soon see an honest emulation among
the married women, which of them could bring the fattest child to the
market. Men would become as fond of their wives, during the time of
their pregnancy, as they are now of their mares in foal, their cows in
calf, or sows when they are ready to farrow; nor offer to beat or kick
them (as is too frequent a practice) for fear of a miscarriage.
Many other advantages might be enumerated. For instance, the addition
of some thousand carcasses in our exportation of barrel’d beef: the
propagation of swine’s flesh, and improvement in the art of making good
bacon, so much wanted among us by the great destruction of pigs, too
frequent at our tables; which are no way comparable in taste or
magnificence to a well grown, fat yearling child, which roasted whole
will make a considerable figure at a Lord Mayor’s feast, or any other
publick entertainment. But this, and many others, I omit, being
studious of brevity.
Supposing that one thousand families in this city, would be constant
customers for infants flesh, besides others who might have it at merry
meetings, particularly at weddings and christenings, I compute that
Dublin would take off annually about twenty thousand carcasses; and the
rest of the kingdom (where probably they will be sold somewhat cheaper)
the remaining eighty thousand.
I can think of no one objection, that will possibly be raised against
this proposal, unless it should be urged, that the number of people
will be thereby much lessened in the kingdom. This I freely own, and
was indeed one principal design in offering it to the world. I desire
the reader will observe, that I calculate my remedy for this one
individual Kingdom of Ireland, and for no other that ever was, is, or,
I think, ever can be upon Earth. Therefore let no man talk to me of
other expedients: Of taxing our absentees at five shillings a pound: Of
using neither clothes, nor houshold furniture, except what is of our
own growth and manufacture: Of utterly rejecting the materials and
instruments that promote foreign luxury: Of curing the expensiveness of
pride, vanity, idleness, and gaming in our women: Of introducing a vein
of parsimony, prudence and temperance: Of learning to love our country,
wherein we differ even from Laplanders, and the inhabitants of
Topinamboo: Of quitting our animosities and factions, nor acting any
longer like the Jews, who were murdering one another at the very moment
their city was taken: Of being a little cautious not to sell our
country and consciences for nothing: Of teaching landlords to have at
least one degree of mercy towards their tenants. Lastly, of putting a
spirit of honesty, industry, and skill into our shopkeepers, who, if a
resolution could now be taken to buy only our native goods, would
immediately unite to cheat and exact upon us in the price, the measure,
and the goodness, nor could ever yet be brought to make one fair
proposal of just dealing, though often and earnestly invited to it.
Therefore I repeat, let no man talk to me of these and the like
expedients, till he hath at least some glympse of hope, that there will
ever be some hearty and sincere attempt to put them into practice.
But, as to myself, having been wearied out for many years with offering
vain, idle, visionary thoughts, and at length utterly despairing of
success, I fortunately fell upon this proposal, which, as it is wholly
new, so it hath something solid and real, of no expence and little
trouble, full in our own power, and whereby we can incur no danger in
disobliging England. For this kind of commodity will not bear
exportation, and flesh being of too tender a consistence, to admit a
long continuance in salt, although perhaps I could name a country,
which would be glad to eat up our whole nation without it.
After all, I am not so violently bent upon my own opinion, as to reject
any offer, proposed by wise men, which shall be found equally innocent,
cheap, easy, and effectual. But before something of that kind shall be
advanced in contradiction to my scheme, and offering a better, I desire
the author or authors will be pleased maturely to consider two points.
First, As things now stand, how they will be able to find food and
raiment for a hundred thousand useless mouths and backs. And secondly,
There being a round million of creatures in humane figure throughout
this kingdom, whose whole subsistence put into a common stock, would
leave them in debt two million of pounds sterling, adding those who are
beggars by profession, to the bulk of farmers, cottagers and labourers,
with their wives and children, who are beggars in effect; I desire
those politicians who dislike my overture, and may perhaps be so bold
to attempt an answer, that they will first ask the parents of these
mortals, whether they would not at this day think it a great happiness
to have been sold for food at a year old, in the manner I prescribe,
and thereby have avoided such a perpetual scene of misfortunes, as they
have since gone through, by the oppression of landlords, the
impossibility of paying rent without money or trade, the want of common
sustenance, with neither house nor clothes to cover them from the
inclemencies of the weather, and the most inevitable prospect of
intailing the like, or greater miseries, upon their breed for ever.
I profess in the sincerity of my heart, that I have not the least
personal interest in endeavouring to promote this necessary work,
having no other motive than the publick good of my country, by
advancing our trade, providing for infants, relieving the poor, and
giving some pleasure to the rich. I have no children, by which I can
propose to get a single penny; the youngest being nine years old, and
my wife past child-bearing.
Last year, I coined the term enshittification to describe the way that platforms decay. That obscene little word did big numbers, it really hit the zeitgeist. I mean, the American Dialect Society made it their Word of the Year for 2023 (which, I suppose, means that now I am definitely getting a poop emoji on my tombstone).
So what is enshittification and why did it catch fire? It is my theory explaining how the internet was colonized by platforms, and why all those platforms are degrading so quickly and thoroughly, and why it matters and what we can do about it.
We are all living through the enshittocene, a great enshittening, in which the services that matter to us, that we rely on, are turning into giant piles of shit.
...@@ -68,4 +68,4 @@ Once it's installed you can just follow the on-screen instructions to make a new ...@@ -68,4 +68,4 @@ Once it's installed you can just follow the on-screen instructions to make a new
I'm gonna throw up a second file that goes through basic Python syntax very soon, either later this evening or tomorrow morning. In the meantime I hope this small write up and the video have helped you in some way. Good luck with the labs, if you have any questions: I'm gonna throw up a second file that goes through basic Python syntax very soon, either later this evening or tomorrow morning. In the meantime I hope this small write up and the video have helped you in some way. Good luck with the labs, if you have any questions:
[pat.prochacki@strath.ac.uk](mailto:pat.prochacki@strath.ac.uk) [pat.prochacki@strath.ac.uk](mailto:pat.prochacki@strath.ac.uk)
\ No newline at end of file
# Python Syntax vs Java
Python and Java are very different when it comes to coding within them. Python is a lot less structured, this file will go over similarities and differences between the two to hopefully help you guys out!
## Hello World
### Python
```python
print("Hello World")
```
### Java
```java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
```
As you can see, Python is a lot simpler as you can just "start" coding without having to do all the surrounding method declarations and things like that.
You *can* have a main method in python, if you'd like, though that tends to be more useful for larger programs that use multiple files. Here's how that's done:
```python
def main():
print("Hello World")
if __name__ == "__main__":
main()
```
## Variable Declarations
Java:
```java
String name = "Alice";
int age = 30;
```
Python:
```python
name = "Alice"
age = 30
```
Note: In Python, variables are not explicitly typed. The interpreter infers the type dynamically.
## Basic Data Types
Strings: 'hello', "world"
Integers: 42, -1
Floats: 3.14, -0.001
Booleans: True, False
## Control Structures
### If-Else
Java:
```java
if (age > 18) {
System.out.println("Adult");
} else {
System.out.println("Minor");
}
```
Python:
```python
if age > 18:
print("Adult")
else:
print("Minor")
```
Note: Python uses indentation instead of curly braces to define blocks.
## Loops
For Loop (Java):
```java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
```
For Loop (Python):
```python
for i in range(5):
print(i)
```
While Loop (Java):
```java
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```
While Loop (Python):
```python
i = 0
while i < 5:
print(i)
i += 1
```
5. Functions
Java:
```java
public static int addNumbers(int a, int b) {
return a + b;
}
```
Python:
```python
def add_numbers(a, b):
return a + b
```
Note: Python functions start with the def keyword. No need to specify return types.
## Lists and Dictionaries
List (Similar to Java's ArrayList):
```python
numbers = [1, 2, 3, 4, 5]
```
Dictionary (Similar to Java's HashMap):
```python
person = {"name": "Alice", "age": 30}
```
## Comments
Java:
```java
// This is a single line comment
/* This is a multi-line comment */
```
Python:
```python
# This is a single line comment
```
Note: Python does not have a native syntax for multi-line comments, but you can surround the comment in quoutes as a workaround