Skip to content

Instantly share code, notes, and snippets.

@svenk
Last active January 24, 2016 18:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save svenk/b02b86e8f8063c676683 to your computer and use it in GitHub Desktop.
Save svenk/b02b86e8f8063c676683 to your computer and use it in GitHub Desktop.
Proposal for Punchcard modeling in Python
#!/usr/bin/python
# python 2
#
from pypunchcards import *
from mappings import h14, m200uc
finished_cards = []
card = Card()
for line in fileinput.input():
line = line.strip()
match = re.match(r"^6(\d\d)\s+0x([0-9a-f]{2})\s+0x([0-9a-f]{2})\s*$", line, re.IGNORECASE)
if(not match):
print "%s, line %d: not a valid line: '%s'" % (fileinput.filename(), fileinput.lineno(), line)
continue
punch_col, hex1, hex2 = match.groups()
# convert ints and hexes.
punch_col = int(punch_col)
hex1 = codecs.decode(hex1, 'hex_codec')
hex2 = codecs.decode(hex2, 'hex_codec')
# depending on our gracefulness, decide when to start new card
start_new_card = punch_col in card.columns.keys() or punch_col == 0
if start_new_card:
print "Finished card"
if not card.is_complete()
print "But card not complete!"
finished_cards.append(card)
card = Card()
# have fun with the bytes
bytes = [Byte(hex1), Byte(hex2)]
column = h14.decode(bytes)
card.set(punch_col, column)
# print all the cards or so.
print h14.encode_card(card)
from pypunchcards import *
# verbose numbers: Indices in Card rows
col0, col1, col2, col3, col4, col5 = 0, 1, 2, 3, 4, 5
col6, col7, col8, col9, col11, col12 = 6, 7, 8, 9, 10, 11
# Hex-Format, das vom Documation M200 angebundenen Microcontroller
# ausgegeben wird
# untested, there may be mistakes
m200uc = CardsByteMapping(bytes=2)
m200uc.set(col0, byte=0, bit=0b00000001)
m200uc.set(col1, byte=0, bit=0b00000010)
m200uc.set(col2, byte=0, bit=0b00000100)
m200uc.set(col3, byte=0, bit=0b00001000)
m200uc.set(col4, byte=0, bit=0b00010000)
m200uc.set(col5, byte=0, bit=0b00100000)
m200uc.set(col6, byte=0, bit=0b01000000)
m200uc.set(col7, byte=0, bit=0b10000000)
m200uc.set(col8, byte=1, bit=0b00000001)
m200uc.set(col9, byte=1, bit=0b00000010)
m200uc.set(col11,byte=1, bit=0b00000100)
m200uc.set(col12,byte=1, bit=0b00001000)
# h14-Format von R. Langf.
# ich weiss nicht, was Spalten "&" und "-" sind
# untested, there may be mistakes
col_ampersand = 10
col_minus = 11
h14 = CardsByteMapping(bytes=2)
h14.set(col6, byte=0, bit=0b10000000)
h14.set(col7, byte=0, bit=0b01000000)
h14.set(col8, byte=0, bit=0b00100000)
h14.set(col9, byte=0, bit=0b00010000)
h14.set(col_ampersand, byte=1, bit=0b00000001)
h14.set(col_minus, byte=1, bit=0b00000010)
h14.set(col0, byte=1, bit=0b00000100)
h14.set(col1, byte=1, bit=0b00001000)
h14.set(col2, byte=1, bit=0b00010000)
h14.set(col3, byte=1, bit=0b00100000)
h14.set(col4, byte=1, bit=0b01000000)
h14.set(col5, byte=1, bit=0b10000000)
# Format nach
# http://homepage.cs.uiowa.edu/~jones/cards/format.html
# untested, there may be mistakes
douglasJones = CardsByteMapping(bytes=3, cards=2)
douglasJones.set(col12, card=0, byte=0, bit=0b10000000)
douglasJones.set(col11, card=0, byte=0, bit=0b01000000)
douglasJones.set( col0, card=0, byte=0, bit=0b00100000)
douglasJones.set( col1, card=0, byte=0, bit=0b00010000)
douglasJones.set( col2, card=0, byte=0, bit=0b00001000)
douglasJones.set( col3, card=0, byte=0, bit=0b00000100)
douglasJones.set( col4, card=0, byte=0, bit=0b00000010)
douglasJones.set( col5, card=0, byte=0, bit=0b00000001)
douglasJones.set( col6, card=0, byte=1, bit=0b10000000)
douglasJones.set( col7, card=0, byte=1, bit=0b01000000)
douglasJones.set( col8, card=0, byte=1, bit=0b00100000)
douglasJones.set( col9, card=0, byte=1, bit=0b00010000)
douglasJones.set(col12, card=1, byte=1, bit=0b00001000)
douglasJones.set(col11, card=1, byte=1, bit=0b00000100)
douglasJones.set( col0, card=1, byte=1, bit=0b00000010)
douglasJones.set( col1, card=1, byte=1, bit=0b00000001)
douglasJones.set( col2, card=1, byte=2, bit=0b10000000)
douglasJones.set( col3, card=1, byte=2, bit=0b01000000)
douglasJones.set( col4, card=1, byte=2, bit=0b00100000)
douglasJones.set( col5, card=1, byte=2, bit=0b00010000)
douglasJones.set( col6, card=1, byte=2, bit=0b00001000)
douglasJones.set( col7, card=1, byte=2, bit=0b00000100)
douglasJones.set( col8, card=1, byte=2, bit=0b00000010)
douglasJones.set( col9, card=1, byte=2, bit=0b00000001)
This gist was an experiment to explore ways to model punch cards with Python nicely.
Focus was spent on good reability/introspection and fault tolerance (incomplete
punch cards/tristates) and not on performance.
#!/usr/bin/python
# This is a Python 2 file
#
# This file holds classes to represent, manipulate and translate 72x13 hole Punch Cards.
# This is more like a proof of concept and a NON running, not tested prototype.
#
# SK Jan 2016 Public Domain
# Needs: python-bitarray, more basic
from bitarray import *
# Alternative for evaluation: python-bitstring, more complete
# python internals
import sys
import fileinput
import re
from collections import namedtuple
import codecs
from copy import deepcopy
from math import log
class Row:
"""
lower, upper = Byte(0x82), Byte(0x10)
col = CardRow()
col.set("col1", lower.bit3)
col.set("col2", lower.bit4)
...
card.set(position, col)
"""
columns = ["col0", "col1", "col2", "col3", "col4", "col5", "col6", "col7",
"col8", "col9", "col11", "col12", "col13"]
values = {}
def __init__(column_names=columns):
for col in columns:
values[col] = False
def set(idx, value):
values[idx] = value
def get(self, idx):
return values[idx]
class Card:
"""
A class representing a cunch card as a dictionary mapping row keys (int)
to Row instances.
"""
def __init__(self, columns=80, rows=13):
self.columns = {}
self.min_col = 0
self.max_col = columns-1
self.keys = range(min_col, max_col+1)
self.num_columns = columns
self.num_rows = rows
self.clear()
def clear(self):
for i in self.keys:
self.columns[i] = Row()
def set(self, col_idx, column):
if not col_idx in self.keys:
raise ValueError("Index out of bounds")
self.columns[col_idx] = column
def missing_columns(self):
wanted_keys = self.keys
available_keys = self.columns.keys()
missing_keys = list(set(wanted_keys) - set(available_keys))
return missing_keys
def is_complete(self):
return not self.missing_columns() # empty list
def dump(self, ignore_missing=False):
if not ignore_missing and not self.is_complete():
raise ValueError("Card is not complete")
for i in self.keys:
if ignore_missing and i in self.missing_columns():
print "%i: missing" % i
continue
print "%i: %s" % (i, str(self.columns[i]))
def __repr__(self):
return 'Card(%i columns, %i filled)' % (len(self.keys), len(self.keys)-len(self.missing_columns()))
class Word(list):
"""
Poor mans implementation of a bitarray.
This was worked out as an alternative to bitstream/bitarray classes.
byte = Word(length=8)
"""
# masks
bit0, bit1, bit2, bit3 = 0b1000000, 0b0100000, 0b0010000, 0b0001000
bit4, bit5, bit6, bit7 = 0b0001000, 0b0000100, 0b0000010, 0b0000001
def __init__(self, byte=0):
pass
def __init__(self, byte=0):
self.bits = []
self.set(byte)
def set(self, byte):
for bit in self.keys():
self.set(bit, byte)
def set(self, bit, byte):
setattr(self, bit, byte | getattr(self, bit))
def keys(self):
return [attr for attr in dir(self) if not callable(getattr(self,attr)) and not attr.startswith("__")]
class WordMapping:
"""
A class which maps different word lengths at each other by alignment.
We define two word types, A and B with individual bit length lenA and lenB.
Then numA objects of type A shall carry the same content as numB objects of type B.
This mapping may be purely randomly defined by identifying positions of bits
in the chunk with length numA*lenA with bits in the chunk with length numB*lenB.
This Mapping class has a distinguished direction: A->B.
Translating A->B is called Encoding.
Translating B->A is called Decoding.
A and B must be classes accessible like arrays with [] (getitem, setitem).
Actually A and B also can be functions returning class instances. They just have to
be callable like A() and B().
"""
def __init__(self, A, B, numA, numB):
self.A, self.B = A, B
self.exampleA, self.exampleB = A(), B()
self.numA, self.numB = numA, numB
self.map = {}
def set(self, idxA, posA, idxB, posB):
if idxA > len(self.exampleA) or idxB > len(self.exampleB) or posA > self.numA or posB > self.numB:
raise ValueError("Indices out of scope: %s for %s." % (str((idxA,posA,idxB,posB)),self))
self.map[(idxA,posA)] = (idxB,posB)
def get(self, idxA, posA):
return self.map[(idxA,posA)]
def encode(self, wordsA):
if len(wordsA) != self.numA:
raise ValueError("Whaaa.")
wordsB = [self.B()]*self.numB
for (idxA, posA), (idxB, posB) in self.map.iteritems():
wordsB[posB][idxB] = wordsA[posA][idxA]
return wordsB
def decode(self, wordsB):
if len(wordsB) != self.numB:
raise ValueError("Whaaa.")
wordsA = [self.A()]*self.numA
for (idxA, posA), (idxB, posB) in self.map.iteritems():
wordsA[posA][idxA] = wordsB[posB][idxB]
return wordsA
def __repr__(self):
return 'WordMapping(%d x A[%d indices] -> %d x B[%d indices])' % (self.numA, len(self.exampleA), self.numB, len(self.exampleB))
class Byte(bitarray):
def __init__(self, value=0):
bitarray.__init__(self)
if value > 2**8:
raise ValueError("This is a nibble and not a Dampfschiff")
bitstr = bin(value)[2:]
self.append(bitstr)
#def Byte():
# return 8 * bitarray('0')
def CardRow():
return 12 * bitarray('0')
class CardsByteMapping(WordMapping):
"""
Cardsrows->Bytes
A=Cards.
B=Bytes.
"""
def __init__(self, bytes=2, cards=1):
WordMapping.__init__(self, A=CardRow, B=Byte, numA=cards, numB=bytes)
def set(self, column_name, bit, byte=0, card=0):
# here, bit is something like 0b01000000. Determine position of 1.
posbit = log(bit, 2)
if not posbit.is_integer():
raise ValueError("Error: bit should be someting like 0b00001000.")
WordMapping.set(self, idxA=column_name, idxB=int(posbit), posA=card, posB=byte)
## helpers not related to anything with punchcards.
def populate(named_constants):
globals().update({k: k for k in named_constants})
def populate_prefix(prefix, named_list):
"""
eg. populate_prefix("col", range(0,10))
gives variables "col0", "col1" in the global space with same values
"""
populate([str(prefix)+str(i) for i in named_list])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment