Calculator 7 Segment Display W/ Width
Solution 1:
Don't try to produce segments programmatically. Enter them manually, but in a generally encoded way. This encoding should allow you to produce different outputs. Do program these.
Please consider the following code
classSSDigit(object):
"""A 7-segment digit"""def__init__(self):
self.lines= []
ssdig0= SSDigit()
ssdig1.lines.append(" ")
ssdig0.lines.append(" - ")
ssdig0.lines.append(" | | ")
ssdig0.lines.append(" ")
ssdig0.lines.append(" | | ")
ssdig0.lines.append(" - ")
ssdig1.lines.append(" ")
ssdig1= SSDigit()
ssdig1.lines.append(" ")
ssdig1.lines.append(" ")
ssdig1.lines.append(" | ")
ssdig1.lines.append(" ")
ssdig1.lines.append(" | ")
ssdig1.lines.append(" ")
ssdig1.lines.append(" ")
.....
classLineType(object):
"""Each of the 2 line types (1 horizontal segment or 2 vertical),
with their possible representations and segment positions"""def__init__(self):
self.valueForRepr= {}
self.segmentPos= []
classLine(object):
"""Each of the 5 lines a SSDigit has, with its LineType"""def__init__(self):
self.type= None
digits= [ ssdig0, ssdig1, ssdig2, ssdig3, ssdig4, ssdig5, ssdig6, ssdig7, ssdig8, ssdig9 ]
linetype1= LineType()
linetype1.valueForRepr[" "]= [0]
linetype1.valueForRepr[" - "]= [1]
linetype1.segmentPos= [3]
linetype2= LineType()
linetype2.valueForRepr[" "]= [0,0]
linetype2.valueForRepr[" | "]= [0,1]
linetype2.valueForRepr[" | "]= [1,0]
linetype2.valueForRepr[" | | "]= [1,1]
linetype2.segmentPos= [2,4]
typeforline= [ linetype1, linetype2, linetype1, linetype2, linetype1 ]
# Validate error-prone typing !!!for digit in digits :
for linenum, linetype inenumerate(typeforline) :
if digit.lines[linenum] notin linetype.valueForRepr :
print("Error in digit {:d}, line {:d}".format(digit,linenum))
defprintNumber(num):
num= str(num)
for linenum, linetype inenumerate(typeforline) :
line= ""for d in num :
line+= digits[int(d)].lines[linenum]
print( line )
printNumber(3475649560458)
The strings entered for each SSDigit
are just canonical representations. Its structure is only for easy developer visualization. The information required to produce different sizes and forms is encoded through these representations and the other structures.
For example,
defprintNumberDoubleSize(num):
num= str(num)
for linenum, linetype inenumerate(typeforline) :
line= ""for d in num :
line+= digits[int(d)].lines[linenum]
print( line )
printNumberDoubleSize(3475649560458)
Next step is to realize that, allowing for spacing, the display consists of a 7x5 matrix:
01234
0
1 -
2 | |
3 -
4 | |
5 -
6
And that each line and column in the matrix are logical ones, i.e. can consist of several physical lines and/or columns, like in:
01234000123000010----20 | |
1 | |
30----40 | |
1 | |
50----60
Here, most logical rows and columns consist of only one physical row and column, respectively, except logical rows 2 and 4 (with 2 physical lines each), and logical column 2, with 4 physical columns.
This can be represented as a series of strings. And it can result very convenient to express for each element how we would like to see it in an off and on state. In the following definitions I indulged in some artistic liberty just for the sake of the example:
phyLineN= []
phyLineN.append([])
phyLineN[0]= []
phyLineN[0].append([ "....", ".", "....",".", "...." ])
phyLineN.append([])
phyLineN[1]= []
phyLineN[1].append([ ". ", " ", ". . "," ", " " ])
phyLineN.append([])
phyLineN[2]= []
phyLineN[2].append([ ". ", ".", " ",".", " " ])
phyLineN[2].append([ ". ", " ", " "," ", " " ])
phyLineN.append([])
phyLineN[3]= []
phyLineN[3].append([ ". ", " ", ". . "," ", " " ])
phyLineN.append([])
phyLineN[4]= []
phyLineN[4].append([ ". ", ".", " ",".", " " ])
phyLineN[4].append([ ". ", " ", " "," ", " " ])
phyLineN.append([])
phyLineN[5]= []
phyLineN[5].append([ ". ", " ", ". . "," ", " " ])
phyLineN.append([])
phyLineN[6]= []
phyLineN[6].append([ "....", ".", "....",".", "...." ])
phyLineY= []
phyLineY.append([])
phyLineY[0]= []
phyLineY[0].append([ " ", " ", " "," ", " " ])
phyLineY.append([])
phyLineY[1]= []
phyLineY[1].append([ " ", " ", "===="," ", " " ])
phyLineY.append([])
phyLineY[2]= []
phyLineY[2].append([ " ", "H", " ","H", " " ])
phyLineY[2].append([ " ", "H", " ","H", " " ])
phyLineY.append([])
phyLineY[3]= []
phyLineY[3].append([ " ", " ", "===="," ", " " ])
phyLineY.append([])
phyLineY[4]= []
phyLineY[4].append([ " ", "H", " ","H", " " ])
phyLineY[4].append([ " ", "H", " ","H", " " ])
phyLineY.append([])
phyLineY[5]= []
phyLineY[5].append([ " ", " ", "===="," ", " " ])
phyLineY.append([])
phyLineY[6]= []
phyLineY[6].append([ " ", " ", " "," ", " " ])
defprintNumberNY(num,structN,structY):
phyRowH= [ len(structN[0]), len(structN[1]), len(structN[2]), len(structN[3]), len(structN[4]), len(structN[5]), len(structN[6]) ]
# Validate structure and compute phyColW# This could be moved to an object constructor so is computed only once
first= 1for line in structN :
for phyLine in line :
if first :
phyColW= [ len(phyLine[0]), len(phyLine[1]), len(phyLine[2]), len(phyLine[3]), len(phyLine[4]) ]
first= 0else:
for i, _ inenumerate(phyLine) :
iflen(phyLine[i]) != phyColW[i] : raise"Inconsistent physical column width"# Real rendering of the (full) number in 7-segment form
num= str(num)
for linenum, linetype inenumerate(typeforline) :
for phyLine inrange(phyRowH[linenum]) :
line= ""for d in num :
for col, qq inenumerate(phyColW) :
if digits[int(d)].lines[linenum][col] != " " :
line+= structY[linenum][phyLine][col]
else:
line+= structN[linenum][phyLine][col]
print( line )
printNumberNY(3475649560458,phyLineN,phyLineY)
The code for printNumberNY
is not much more difficult than the one for the simple case of width*n.
The case of width*n is, in fact, a particular case of this setup, and can be constructed with:
def sizeVH(vSegHeight,hSegWidth,vSep,hSep):
hSepStr= " " *hSep
hSegN= " "* hSegWidth
hSegY= "-"* hSegWidth
phyLineN= []
phyLineN.append([])
phyLineN[0]= []
phyLineN.append([])
phyLineN[1]= []
phyLineN[1].append([ "", " ", hSegN," ", hSepStr ])
phyLineN.append([])
phyLineN[2]= []
for i in range(vSegHeight) :
phyLineN[2].append([ "", " ", hSegN," ", hSepStr ])
phyLineN.append([])
phyLineN[3]= []
phyLineN[3].append([ "", " ", hSegN," ", hSepStr ])
phyLineN.append([])
phyLineN[4]= []
for i in range(vSegHeight) :
phyLineN[4].append([ "", " ", hSegN," ", hSepStr ])
phyLineN.append([])
phyLineN[5]= []
phyLineN[5].append([ "", " ", hSegN," ", hSepStr ])
phyLineN.append([])
phyLineN[6]= []
for i in range(vSep) :
phyLineN[6].append([ "", " ", hSegN," ", hSepStr ])
phyLineY= []
phyLineY.append([])
phyLineY[0]= []
phyLineY.append([])
phyLineY[1]= []
phyLineY[1].append([ "", " ", hSegY," ", hSepStr ])
phyLineY.append([])
phyLineY[2]= []
for i in range(vSegHeight) :
phyLineY[2].append([ "", "|", hSegN,"|", hSepStr ])
phyLineY.append([])
phyLineY[3]= []
phyLineY[3].append([ "", " ", hSegY," ", hSepStr ])
phyLineY.append([])
phyLineY[4]= []
for i in range(vSegHeight) :
phyLineY[4].append([ "", "|", hSegN,"|", hSepStr ])
phyLineY.append([])
phyLineY[5]= []
phyLineY[5].append([ "", " ", hSegY," ", hSepStr ])
phyLineY.append([])
phyLineY[6]= []
for i in range(vSep) :
phyLineY[6].append([ "", " ", hSegN," ", hSepStr ])
return (phyLineN,phyLineY)
phyLineN, phyLineY= sizeVH(4,6,1,3)
printNumberNY(3475649560458,phyLineN,phyLineY)
I know that I didn't use some of the elements I defined at the beginning, but this is how I would have modeled it. They could be useful if we continue extending the solution.
Solution 2:
Haha, what a fun problem!
DISP = 7# 1#2 3# 4#5 6# 7defdigit(cur, size = 5, ch = '*'):
defdraw(led_code):
for a, b, c in led_code:
if a:
print' ' + ch * size + ' 'if b and c:
print (ch + ' ' * size + ch + '\n') * size
continueif b:
print (ch + ' ' * size + ' ' + '\n') * size
if c:
print (' ' + ' ' * size + ch + '\n') * size
digits = {
1 : [(0,0,1),(0,0,1),(0,0,0)],
0 : [(1,1,1),(0,1,1),(1,0,0)]
}
draw(digits.get(cur, digits[1]))
printfor x inbin(42).split('b')[1]:
digit(int(x))
Solution 3:
I will take this as a fun exercise (and maybe my solution gives you some ideas):
from collections import defaultdict
classCell:
def__init__ (self, width = 4, height = 2, hChar = '*', vChar = '*'):
self.width = width
self.height = height
self.hChar = hChar
self.vChar = vChar
defshowSegments (self, segments):
defchar (segment):
if segment notin segments: return' 'return self.hChar if segment in (0, 3, 6) else self.vChar
lines = []
lines.append (' ' + char (0) * self.width + ' ')
for _ inrange (self.height):
lines.append (char (1) + ' ' * self.width + char (2) )
lines.append (' ' + char (3) * self.width + ' ')
for _ inrange (self.height):
lines.append (char (4) + ' ' * self.width + char (5) )
lines.append (' ' + char (6) * self.width + ' ')
return lines
classDisplay:
def__init__ (self, encoding, cells, padding = 1, width = 4, height = 2, hChar = '*', vChar = '*'):
self.encoding = encoding
self.padding = padding
self.cells = [Cell (width, height, hChar, vChar) for _ inrange (cells) ]
defshow (self, string):
cellLines = []
for idx, c inenumerate (string):
if idx >= len (self.cells): break
cellLines.append (self.cells [idx].showSegments (self.encoding [c] ) )
ifnot cellLines: return
cellLines = zip (*cellLines)
print ('\n'.join ( (' ' * self.padding).join (line) for line in cellLines) )
encoding = defaultdict (lambda: {} )
encoding ['0'] = {0, 1, 2, 4, 5, 6}
encoding ['1'] = {2, 5}
encoding ['2'] = {0, 2, 3, 4, 6}
encoding ['3'] = {0, 2, 3, 5, 6}
d = Display (encoding, 5, 2)
d.show ('12301')
Solution 4:
I think the solution here is to just start small and work your way forward until the whole program is finished.
First write a function that can draw a single digit, say, drawTwo()
, which draws the digit two. Once you have this figured out, refactor this into drawTwo(width)
, which draws the digit with the right width. Now that you have this figured out, it shouldn't be too hard to write one for each digit zero through ten.
Once you have your ten functions, write a function that splits your input number into its digits and calls the correct function (possibly using a switch statement) for each digit.
Just take it one step at a time.
Post a Comment for "Calculator 7 Segment Display W/ Width"