Related
I have been packaging a script to calculate all possible entries in the empty cells of a sudoku game. While the algorithm to screen the vertical column and the horizontal row works, it seems that my script is not able to screen the relevant box where the empty cell is located.
The code that I am using is the following:
def possible(y,x,n):
global grid
for i in range(0,9):
if grid[y][i] == n:
return False
for i in range(0,9):
if grid[i][x] == n:
return False
x0 = (x//3)*3
y0 = (y//3)*3
for i in range(0,3):
for j in range(0,3):
if (grid[y0+i][x0+j] == n):
#print((x0+j),end=' ')
#print((y0+i),end=' ')
return False
list.append(y+1)
list.append(x+1)
list.append(n)
return True
It seems that there is some problem with the append procedure.....
Any assistance is welcome
My general comments:
Seems like you are trying to append to a list which might or might
not be defined outside of the possible() function (it's not in the supplied code).
However, as it is
not defined within the scope of that function, you generally can't
access it from the inside. Related read.)
Also you should change a variable name as
list is a built-in type of Python and it is not
recommended to use builtin types as variable
names unless you absolutely need to do so for some reason.
Generally it is not a best practice to use global variables.
My suggestion would be to move the gathering of possible
numbers outside of this function. Example:
def possible(grid: list[list[int]], num: int, pos: tuple[int, int]) -> bool:
# Check row
if num in grid[pos[0]]:
return False
# Check column
if num in [item[pos[1]] for item in grid]:
return False
# Check box
box_x = pos[1] // 3
box_y = pos[0] // 3
for i in range(box_y * 3, box_y * 3 + 3):
if num in grid[i][box_x * 3: box_x * 3 + 3] \
and (i, grid[i].index(num)) != pos:
return False
return True
Then run this 'cleaner' function in a for loop or list comprehension to collect possible numbers for a given position on the Sudoku grid.
For example (for cycle):
possible_values = []
for i in range(1,10):
if possible(grid, i, (x, y)):
possible_values.append(i)
Or this (list comprehension):
possible_values = [n for n in range(1,10) if possible(grid, n, (0, 2))]
In the Sudoku game world one call the "possible entries" of the empty cells, candidates or pencil-marks.
Here is how we can identify the candidates of the empty cells.
grid = [
[0, 0, 0, 6, 0, 8, 9, 1, 0],
[6, 0, 2, 0, 9, 0, 3, 4, 0],
[1, 9, 8, 3, 0, 0, 0, 6, 7],
[0, 5, 9, 0, 0, 0, 4, 2, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 1, 3, 0, 2, 0, 8, 0, 0],
[9, 6, 0, 5, 3, 7, 2, 8, 0],
[2, 0, 0, 4, 1, 0, 0, 3, 0],
[3, 4, 0, 2, 8, 0, 1, 7, 9],
]
candidates=bytearray(729)
def identifyCandidates():
for cell in range(81):
row,col=divmod(cell,9)
if grid[row][col] == 0 :
for kan in range(1,10):
if not clueInSector(cell, kan):
candidates[9*cell+(kan - 1)]=1
def clueInSector(cell, clue):
cellrow,cellcol = divmod(cell,9)
for col in range(9):
if (col != cellcol and grid[cellrow][col] == clue) :
return True
for row in range(9):
if (row != cellrow and grid[row][cellcol] == clue) :
return True
rowB = 3 * ((cellrow) // 3)
colB = 3 * ((cellcol) // 3)
for row in range (rowB,rowB + 3) :
for col in range(colB,colB +3) :
if (col != cellcol and row != cellrow and grid[row][col] == clue) :
return True
return False
Print of the 13 first cells:
cell:0 candidates: 5.
cell:1 candidates: 3.7.
cell:2 candidates: 4.5.7.
cell:3 no candidate.
cell:4 candidates: 4.5.7.
cell:5 no candidate.
cell:6 no candidate.
cell:7 no candidate.
cell:8 candidates: 2.5.
cell:9 no candidate.
cell:10 candidates: 7.
cell:11 no candidate.
cell:12 candidates: 1.7.
import numpy as np
def row(board,x,y):
"""Takes in a board and x y coordinates and returns all
the row candidates"""
numbers = np.arange(1,10)
missing = []
for number in numbers:
if number not in board[x]:
missing.append(number)
else:
continue
return missing
def column(board,x,y):
"""Takes an incomplete board and returns all the
column candidates"""
numbers = np.arange(1,10)
missing = []
for number in numbers:
if number not in board[:,y]:
missing.append(number)
else:
continue
return missing
def box(board,x,y):
"""Takes an incomplete board, coordinates and returns the
box wise candidates"""
numbers = list(range(1,10))
missing = []
box1 = np.array([board[0,0:3],board[1,0:3],board[2,0:3]])
box2 = np.array([board[0,3:6],board[1,3:6],board[2,3:6]])
box3 = np.array([board[0,6:10],board[1,6:10],board[2,6:10]])
box4 = np.array([board[3,0:3],board[4,0:3],board[5,0:3]])
box5 = np.array([board[3,3:6],board[4,3:6],board[5,3:6]])
box6 = np.array([board[3,6:10],board[4,6:10],board[5,6:10]])
box7 = np.array([board[6,0:3],board[7,0:3],board[8,0:3]])
box8 = np.array([board[6,3:6],board[7,3:6],board[8,3:6]])
box9 = np.array([board[6,6:10],board[7,6:10],board[8,6:10]])
condition1 = 0<=x<=2 and 0<=y<=2
condition2 = 0<=x<=2 and 3<=y<=5
condition3 = 0<=x<=2 and 6<=y<=8
condition4 = 3<=x<=5 and 0<=y<=2
condition5 = 3<=x<=5 and 3<=y<=5
condition6 = 3<=x<=5 and 6<=y<=8
condition7 = 6<=x<=8 and 0<=y<=2
condition8 = 6<=x<=8 and 3<=y<=5
condition9 = 6<=x<=8 and 6<=y<=8
if condition1:
for number in numbers:
if number not in box1:
missing.append(number)
else:
continue
if condition2:
for number in numbers:
if number not in box2:
missing.append(number)
else:
continue
if condition3:
for number in numbers:
if number not in box3:
missing.append(number)
else:
continue
if condition4:
for number in numbers:
if number not in box4:
missing.append(number)
else:
continue
if condition5:
for number in numbers:
if number in box5:
continue
else:
missing.append(number)
if condition6:
for number in numbers:
if number not in box6:
missing.append(number)
else:
continue
if condition7:
for number in numbers:
if number not in box7:
missing.append(number)
else:
continue
if condition8:
for number in numbers:
if number not in box8:
missing.append(number)
else:
continue
if condition9:
for number in numbers:
if number not in box9:
missing.append(number)
else:
continue
return missing
def sudsolver(board):
"""Give it a board andt it will solve it for your using the functions defined above."""
newboard = board.copy()
for index,n in np.ndenumerate(board):
if board[index] == 0:
x = index[0]
y = index[1]
boxsolution = box(newboard,x,y)
columnsolution = column(newboard,x,y)
rowsolution = row(newboard,x,y)
if len(boxsolution) or len(columnsolution) or len(rowsolution) < 1:
for number in boxsolution:
if number in columnsolution and number in rowsolution:
newboard[index] = number
else:
continue
else:
continue
return newboard
testboard = np.array([
[0, 0, 0, 3, 7, 0, 0, 5, 6],
[5, 0, 0, 0, 1, 0, 9, 7, 0],
[0, 6, 0, 9, 8, 0, 3, 4, 0],
[0, 0, 7, 0, 0, 2, 0, 8, 0],
[0, 0, 9, 0, 3, 0, 6, 0, 0],
[0, 5, 0, 8, 0, 0, 2, 0, 0],
[0, 7, 5, 0, 6, 9, 0, 2, 0],
[0, 4, 8, 0, 2, 0, 0, 0, 5],
[2, 9, 0, 0, 5, 8, 0, 0, 0]
])
pleasework = sudsolver(testboard)
I have created different functions to check the solutions of a given cell, however, when the board is returned from the sudsolver function, the board still has a few 0's in it.
The board which I am using is called testboard and I have been assured that it is possible to solve.
I cannot think of why this is and how to solve it. Any help would be great.
I'm trying to convert unicode text to string literally, but I don't seem to find a way to do this.
input= u'/123/123/123'
convert to string:
output="/123/123/123"
If I try to do str(), it will encode it and if I try to loop over the text and convert letter by letter, it will give me each one of the unicode characters.
EDIT: Take into consideration that the objective is not to convert the string but to take the letters in the unicode text and create a string. If I follow the link provided in the comment:
Convert a Unicode string to a string in Python (containing extra symbols)
import unicodedata
unicodedata.normalize('NFKD', input).encode('ascii','ignore')
output='SSS'
and as it is possible to see..it is not the expected output.
Edit: I wrote as an example the unicode u'/123' but Im trying to convert chinese characters, example:
a=u'\u6c34'
str(a)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u6c34' in position 0: ordinal not in range(128)
output_expected="\u6c34"
I've tried to convert it with str() as you mention in your question, and it does work for me. You can check the encoding with type().
>>> input= u'/123/123/123'
>>> type(input)
<type 'unicode'>
>>> output=str(input)
>>> print output
/123/123/123
>>> type(output)
<type 'str'>
How do you try to iterate among the letters? I've tried and they are still as a string. You could convert the input first and then do whatever you want once they are str:
letters = [x for x in output]
for letter in letters:
... print type(letter)
...
I hope it helps!
Here's how to do it the easy way:
>>> a=u'\x83\u6c34\U00103ABC'
>>> a.encode('unicode_escape')
'\\x83\\u6c34\\U00103abc'
>>> print a.encode('unicode_escape')
\x83\u6c34\U00103abc
Here's how to do it the hard way.
ascii_printable = set(unichr(i) for i in range(0x20, 0x7f))
def convert(ch):
if ch in ascii_printable:
return ch
ix = ord(ch)
if ix < 0x100:
return '\\x%02x' % ix
elif ix < 0x10000:
return '\\u%04x' % ix
return '\\U%08x' % ix
output = ''.join(convert(ch) for ch in input)
For Python 3 use chr instead of unichr.
Somebody wrote a really complete code for doing this, so cool, sources:
import unicodedata
def fix_bad_unicode(text):
if not isinstance(text, unicode):
raise TypeError("This isn't even decoded into Unicode yet. "
"Decode it first.")
if len(text) == 0:
return text
maxord = max(ord(char) for char in text)
tried_fixing = []
if maxord < 128:
# Hooray! It's ASCII!
return text
else:
attempts = [(text, text_badness(text) + len(text))]
if maxord < 256:
tried_fixing = reinterpret_latin1_as_utf8(text)
tried_fixing2 = reinterpret_latin1_as_windows1252(text)
attempts.append((tried_fixing, text_cost(tried_fixing)))
attempts.append((tried_fixing2, text_cost(tried_fixing2)))
elif all(ord(char) in WINDOWS_1252_CODEPOINTS for char in text):
tried_fixing = reinterpret_windows1252_as_utf8(text)
attempts.append((tried_fixing, text_cost(tried_fixing)))
else:
# We can't imagine how this would be anything but valid text.
return text
# Sort the results by badness
attempts.sort(key=lambda x: x[1])
#print attempts
goodtext = attempts[0][0]
if goodtext == text:
return goodtext
else:
return fix_bad_unicode(goodtext)
def reinterpret_latin1_as_utf8(wrongtext):
newbytes = wrongtext.encode('latin-1', 'replace')
return newbytes.decode('utf-8', 'replace')
def reinterpret_windows1252_as_utf8(wrongtext):
altered_bytes = []
for char in wrongtext:
if ord(char) in WINDOWS_1252_GREMLINS:
altered_bytes.append(char.encode('WINDOWS_1252'))
else:
altered_bytes.append(char.encode('latin-1', 'replace'))
return ''.join(altered_bytes).decode('utf-8', 'replace')
def reinterpret_latin1_as_windows1252(wrongtext):
return wrongtext.encode('latin-1').decode('WINDOWS_1252', 'replace')
def text_badness(text):
assert isinstance(text, unicode)
errors = 0
very_weird_things = 0
weird_things = 0
prev_letter_script = None
for pos in xrange(len(text)):
char = text[pos]
index = ord(char)
if index < 256:
weird_things += SINGLE_BYTE_WEIRDNESS[index]
if SINGLE_BYTE_LETTERS[index]:
prev_letter_script = 'latin'
else:
prev_letter_script = None
else:
category = unicodedata.category(char)
if category == 'Co':
# Unassigned or private use
errors += 1
elif index == 0xfffd:
# Replacement character
errors += 1
elif index in WINDOWS_1252_GREMLINS:
lowchar = char.encode('WINDOWS_1252').decode('latin-1')
weird_things += SINGLE_BYTE_WEIRDNESS[ord(lowchar)] - 0.5
if category.startswith('L'):
name = unicodedata.name(char)
scriptname = name.split()[0]
freq, script = SCRIPT_TABLE.get(scriptname, (0, 'other'))
if prev_letter_script:
if script != prev_letter_script:
very_weird_things += 1
if freq == 1:
weird_things += 2
elif freq == 0:
very_weird_things += 1
prev_letter_script = script
else:
prev_letter_script = None
return 100 * errors + 10 * very_weird_things + weird_things
def text_cost(text):
"""
Assign a cost function to the length plus weirdness of a text string.
"""
return text_badness(text) + len(text)
WINDOWS_1252_GREMLINS = [
# adapted from http://effbot.org/zone/unicode-gremlins.htm
0x0152, # LATIN CAPITAL LIGATURE OE
0x0153, # LATIN SMALL LIGATURE OE
0x0160, # LATIN CAPITAL LETTER S WITH CARON
0x0161, # LATIN SMALL LETTER S WITH CARON
0x0178, # LATIN CAPITAL LETTER Y WITH DIAERESIS
0x017E, # LATIN SMALL LETTER Z WITH CARON
0x017D, # LATIN CAPITAL LETTER Z WITH CARON
0x0192, # LATIN SMALL LETTER F WITH HOOK
0x02C6, # MODIFIER LETTER CIRCUMFLEX ACCENT
0x02DC, # SMALL TILDE
0x2013, # EN DASH
0x2014, # EM DASH
0x201A, # SINGLE LOW-9 QUOTATION MARK
0x201C, # LEFT DOUBLE QUOTATION MARK
0x201D, # RIGHT DOUBLE QUOTATION MARK
0x201E, # DOUBLE LOW-9 QUOTATION MARK
0x2018, # LEFT SINGLE QUOTATION MARK
0x2019, # RIGHT SINGLE QUOTATION MARK
0x2020, # DAGGER
0x2021, # DOUBLE DAGGER
0x2022, # BULLET
0x2026, # HORIZONTAL ELLIPSIS
0x2030, # PER MILLE SIGN
0x2039, # SINGLE LEFT-POINTING ANGLE QUOTATION MARK
0x203A, # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
0x20AC, # EURO SIGN
0x2122, # TRADE MARK SIGN
]
# a list of Unicode characters that might appear in Windows-1252 text
WINDOWS_1252_CODEPOINTS = range(256) + WINDOWS_1252_GREMLINS
# Rank the characters typically represented by a single byte -- that is, in
# Latin-1 or Windows-1252 -- by how weird it would be to see them in running
# text.
#
# 0 = not weird at all
# 1 = rare punctuation or rare letter that someone could certainly
# have a good reason to use. All Windows-1252 gremlins are at least
# weirdness 1.
# 2 = things that probably don't appear next to letters or other
# symbols, such as math or currency symbols
# 3 = obscure symbols that nobody would go out of their way to use
# (includes symbols that were replaced in ISO-8859-15)
# 4 = why would you use this?
# 5 = unprintable control character
#
# The Portuguese letter à (0xc3) is marked as weird because it would usually
# appear in the middle of a word in actual Portuguese, and meanwhile it
# appears in the mis-encodings of many common characters.
SINGLE_BYTE_WEIRDNESS = (
# 0 1 2 3 4 5 6 7 8 9 a b c d e f
5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, # 0x00
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, # 0x10
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0x20
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0x30
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0x40
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0x50
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0x60
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, # 0x70
2, 5, 1, 4, 1, 1, 3, 3, 4, 3, 1, 1, 1, 5, 1, 5, # 0x80
5, 1, 1, 1, 1, 3, 1, 1, 4, 1, 1, 1, 1, 5, 1, 1, # 0x90
1, 0, 2, 2, 3, 2, 4, 2, 4, 2, 2, 0, 3, 1, 1, 4, # 0xa0
2, 2, 3, 3, 4, 3, 3, 2, 4, 4, 4, 0, 3, 3, 3, 0, # 0xb0
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0xc0
1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, # 0xd0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0xe0
1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, # 0xf0
)
# Pre-cache the Unicode data saying which of these first 256 characters are
# letters. We'll need it often.
SINGLE_BYTE_LETTERS = [
unicodedata.category(unichr(i)).startswith('L')
for i in xrange(256)
]
# A table telling us how to interpret the first word of a letter's Unicode
# name. The number indicates how frequently we expect this script to be used
# on computers. Many scripts not included here are assumed to have a frequency
# of "0" -- if you're going to write in Linear B using Unicode, you're
# probably aware enough of encoding issues to get it right.
#
# The lowercase name is a general category -- for example, Han characters and
# Hiragana characters are very frequently adjacent in Japanese, so they all go
# into category 'cjk'. Letters of different categories are assumed not to
# appear next to each other often.
SCRIPT_TABLE = {
'LATIN': (3, 'latin'),
'CJK': (2, 'cjk'),
'ARABIC': (2, 'arabic'),
'CYRILLIC': (2, 'cyrillic'),
'GREEK': (2, 'greek'),
'HEBREW': (2, 'hebrew'),
'KATAKANA': (2, 'cjk'),
'HIRAGANA': (2, 'cjk'),
'HIRAGANA-KATAKANA': (2, 'cjk'),
'HANGUL': (2, 'cjk'),
'DEVANAGARI': (2, 'devanagari'),
'THAI': (2, 'thai'),
'FULLWIDTH': (2, 'cjk'),
'MODIFIER': (2, None),
'HALFWIDTH': (1, 'cjk'),
'BENGALI': (1, 'bengali'),
'LAO': (1, 'lao'),
'KHMER': (1, 'khmer'),
'TELUGU': (1, 'telugu'),
'MALAYALAM': (1, 'malayalam'),
'SINHALA': (1, 'sinhala'),
'TAMIL': (1, 'tamil'),
'GEORGIAN': (1, 'georgian'),
'ARMENIAN': (1, 'armenian'),
'KANNADA': (1, 'kannada'), # mostly used for looks of disapproval
'MASCULINE': (1, 'latin'),
'FEMININE': (1, 'latin')
}
Then you just call the method:
fix_bad_unicode(u'aあä')
>> u'a\u3042\xe4'
I want to extract a slice of length 10, beginning at index 2, of a numpy array A:
import numpy
A = numpy.array([1,3,5,3,9])
def bigslice(A, begin_at, length):
a = A[begin_at:begin_at + length]
while len(a) + len(A) < length:
a = numpy.concatenate((a,A))
return numpy.concatenate((a, A[:length-len(a)]))
print bigslice(A, begin_at = 2, length = 10)
#[5,3,9,1,3,5,3,9,1,3]
This is correct. But I'm looking for a more efficient way to do this (especially when I'll have arrays of thousands of elements at the end) : I suspect the concatenate used here to recreate lots of new temporary arrays, and that would be un-efficient.
How to do the same thing more efficiently ?
Since the middle part of the array is already known to you (i.e. n repetitions of the full array), you can simply construct the middle portion using np.tile:
def cyclical_slice(A, start, length):
arr_l = len(A)
middle = np.tile(A, length // arr_l)
return np.array([A[start:], middle, A[0:length - len(middle)]])
Your code doesn't seem to guarantee that you get a slice of length length, e.g.
>>> A = numpy.array([1,3,5,3,9])
>>> bigslice(A, 0, 3)
array([1, 3, 5, 3, 9, 1, 3, 5])
Assuming that this is an oversight, maybe you could use np.pad, e.g.
def wpad(A, begin_at, length):
to_pad = max(length + begin_at - len(A), 0)
return np.pad(A, (0, to_pad), mode='wrap')[begin_at:begin_at+length]
which gives
>>> wpad(A, 0, 3)
array([1, 3, 5])
>>> wpad(A, 0, 10)
array([1, 3, 5, 3, 9, 1, 3, 5, 3, 9])
>>> wpad(A, 2, 10)
array([5, 3, 9, 1, 3, 5, 3, 9, 1, 3])
and so on.
I am trying to program a standard snake draft, where team A pick, team B, team C, team C, team B, team A, ad nauseum.
If pick number 13 (or pick number x) just happened how can I figure which team picks next for n number of teams.
I have something like:
def slot(n,x):
direction = 'down' if (int(x/n) & 1) else 'up'
spot = (x % n) + 1
slot = spot if direction == 'up' else ((n+1) - spot)
return slot
I have feeling there is a simpler, more pythonic what than this solution. Anyone care to take a hack at it?
So I played around a little more. I am looking for the return of a single value, rather than the best way to count over a looped list. The most literal answer might be:
def slot(n, x): # 0.15757 sec for 100,000x
number_range = range(1, n+1) + range(n,0, -1)
index = x % (n*2)
return number_range[index]
This creates a list [1,2,3,4,4,3,2,1], figures out the index (e.g. 13 % (4*2) = 5), and then returns the index value from the list (e.g. 4). The longer the list, the slower the function.
We can use some logic to cut the list making in half. If we are counting up (i.e. (int(x/n) & 1) returns False), we get the obvious index value (x % n), else we subtract that value from n+1:
def slot(n, x): # 0.11982 sec for 100,000x
number_range = range(1, n+1) + range(n,0, -1)
index = ((n-1) - (x % n)) if (int(x/n) & 1) else (x % n)
return number_range[index]
Still avoiding a list altogether is fastest:
def slot(n, x): # 0.07275 sec for 100,000x
spot = (x % n) + 1
slot = ((n+1) - spot) if (int(x/n) & 1) else spot
return slot
And if I hold the list as variable rather than spawning one:
number_list = [1,2,3,4,5,6,7,8,9,10,11,12,12,11,10,9,8,7,6,5,4,3,2,1]
def slot(n, x): # 0.03638 sec for 100,000x
return number_list[x % (n*2)]
Why not use itertools cycle function:
from itertools import cycle
li = range(1, n+1) + range(n, 0, -1) # e.g. [1, 2, 3, 4, 4, 3, 2, 1]
it = cycle(li)
[next(it) for _ in xrange(10)] # [1, 2, 3, 4, 4, 3, 2, 1, 1, 2]
Note: previously I had answered how to run up and down, as follows:
it = cycle(range(1, n+1) + range(n, 0, -1)) #e.g. [1, 2, 3, 4, 3, 2, 1, 2, 3, ...]
Here's a generator that will fulfill what you want.
def draft(n):
while True:
for i in xrange(1,n+1):
yield i
for i in xrange(n,0,-1):
yield i
>>> d = draft(3)
>>> [d.next() for _ in xrange(12)]
[1, 2, 3, 3, 2, 1, 1, 2, 3, 3, 2, 1]
from itertools import chain, cycle
def cycle_up_and_down(first, last):
up = xrange(first, last+1, 1)
down = xrange(last, first-1, -1)
return cycle(chain(up, down))
turns = cycle_up_and_down(1, 4)
print [next(turns) for n in xrange(10)] # [1, 2, 3, 4, 4, 3, 2, 1, 1, 2]
Here is a list of numbers that counts up, then down:
>>> [ -abs(5-i)+5 for i in range(0,10) ]
[0, 1, 2, 3, 4, 5, 4, 3, 2, 1]
Written out:
count_up_to = 5
for i in range( 0, count_up_to*2 ):
the_number_you_care_about = -abs(count_up_to-i) + count_up_to
# do stuff with the_number_you_care_about
Easier to read:
>>> list( range(0,5) ) + list( range( 5, 0, -1 ) )
[0, 1, 2, 3, 4, 5, 4, 3, 2, 1]
Written out:
count_up_to = 5
for i in list( range(0,5) ) + list( range(5, 0, -1) ):
# i is the number you care about
Another way:
from itertools import chain
for i in chain( range(0,5), range(5,0,-1) ):
# i is the number you care about