Backtracking algorithm for Sudoku in python - python

I'm trying to use backtracking to make a Sudoku solver. When I work through the code by hand it works perfectly but when I run it I get empty cells in my return solution. I've spent such a ridiculous amount of time trying to fix it but I can't even figure out where exactly its going wrong. I'm fairly certain my function for checking cell solutions is correct. Here's the code:
import numpy as np
board = np.array([[0, 0, 0, 8, 4, 0, 0, 0, 3],
[0, 7, 5, 0, 0, 0, 0, 0, 0],
[0, 4, 3, 0, 0, 6, 0, 0, 0],
[0, 0, 7, 0, 0, 8, 4, 9, 0],
[0, 0, 0, 9, 3, 1, 0, 0, 0],
[0, 5, 2, 7, 0, 0, 8, 0, 0],
[0, 0, 0, 2, 0, 0, 3, 4, 0],
[0, 0, 0, 0, 0, 0, 6, 2, 0],
[2, 0, 0, 0, 7, 3, 0, 0, 0]])
#check if input is viable solution for a cell
def isSolution(row, col, n):
#return 0 for false (not a possible solution)
#return 1 for true (possible solution)
a = 0
for i in range(0,9):
if(board[row,i] == n):
a += 1
if(board[i,col] == n):
a += 1
h = (1 - (2 * ((row % 3) != 0)))
i = (1 - (2 * ((col % 3) != 0)))
j = (2 - (row % 3)**2)
k = (2 - (col % 3)**2)
if(board[row + h, col + i] == n):
a += 1
elif(board[row + h, col + k] == n):
a += 1
elif(board[row + j, col + i] == n):
a += 1
elif(board[row + j, col + k] == n):
a += 1
if(a == 0):
return 1
else:
return 0
def solve():
for row in range(0, 9):
for col in range(0,9):
if(board[row,col] == 0):
for n in range(1, 10):
if(isSolution(row, col, n) == 1):
board[row,col] = n
print(board)
solve()
board[row,col] = 0
return
#main
solve()
Please help if you can I'm trying to get better at python and feel like I've hit a wall here

Expanding comment of Thierry Lathuille
def solve():
for row in range(0, 9):
for col in range(0,9):
if(board[row,col] == 0):
for n in range(1, 10):
if(isSolution(row, col, n) == 1):
board[row,col] = n
# print(board)
if (board != 0).all():
raise StopIteration
solve()
board[row,col] = 0
return
#main
try:
solve()
except StopIteration:
print(board)

Related

Python list appending in a loop not working as intended

A have a case where i receive a integer value(cents) and need to find all the change possibilities with quarters, dimes, nickels and pennies, and return a set of all the ways.
I've made some code that works partially.
QUARTER = 25
DIME = 10
NICKEL = 5
PENNIE = 1
def makeChange(value):
way_list = []
way = [0, 0, 0, 0]
for q_q in range((value // QUARTER) + 1):
way[0] = q_q
value_after_Q = value - (q_q * QUARTER)
for d_q in range((value_after_Q // DIME) + 1):
way[1] = d_q
value_after_D = value_after_Q - (d_q * DIME)
for n_q in range((value_after_D // NICKEL) + 1):
way[2] = n_q
value_after_N = value_after_D - (n_q * NICKEL)
p_q = value_after_N // PENNIE
way[3] = p_q
print(way) # this print shows my results one by one
way_list.append(way) # but this append only appends the last possible result, multiple times
# makes a set:
way_list = [
_way
for ind, _way in enumerate(way_list)
if _way not in way_list[:ind]
]
return way_list
print(makeChange(25))
The print on the last loop prints me:
[0, 0, 0, 25]
[0, 0, 1, 20]
[0, 0, 2, 15]
[0, 0, 3, 10]
[0, 0, 4, 5]
[0, 0, 5, 0]
[0, 1, 0, 15]
[0, 1, 1, 10]
[0, 1, 2, 5]
[0, 1, 3, 0]
[0, 2, 0, 5]
[0, 2, 1, 0]
[1, 0, 0, 0]
Which is not wrong, but i need it inside a set.
When i try to append the "way" list to the propper "way_list", it only appends the [1, 0, 0, 0], multiple times.

Sum a list of numbers until a number 0 is found

I have a data list like the following data = [1, 0, 0, 0, 1, 1, 1, 0, 2, 3, 1, 0, 0, 1, 1, 1, 0] and I want to add up the elements of the list to be like this:
[1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 0, 3, 0], where the previous element is the value 0 and the last element other than 0 is the result of the value of the previous number of elements.
I've tried with the following code, if I do the trace, it looks like it can be done, but when I run it it doesn't show results but it's still in the loop that doesn't stop.
I tried it with :
data = [1, 0, 0, 0, 1, 1, 1, 0]
k = len(data)-1
while True:
print(k)
if(data[k-1] == 0):
continue
elif(data[k] == 0):
print("h")
continue
elif(data[k-1] != 0):
data[k] = data[k] + data[k-1]
data[k-1] = 0
k = k-1
if(k == 0):
break
print(data)
Iterate through the list and just add every time a non - zero number
and append a zero to the list.
when there is a 0 appearing just append the sum and make sum 0.
if the last element is 0 add zero to the last number or the
respective last number.
Just remove the first zero and return the list.
.
data = [1, 0, 0, 0, 1, 1, 1, 0, 2, 3, 1, 0, 0, 1, 1, 1, 0]
def calc(data):
sum = 0
new = []
for i in range(len(data)):
if data[i] == 0:
new.append(sum)
if i == len(data) - 1:
new.append(0)
sum = 0
else:
sum = sum = sum + data[i]
new.append(0)
if i == len(data) - 1:
new.append(sum)
if new[0] == 0:
del new[0]
return new
Here is a very simple implementation. I think it is quite self-explanatory. You iterate over each item n in the list, if n is zero, you have two options a) if there is a previous sum x, append x and then n b) if there is no sum, just append 0.
If n is different from zero, sum it to x.
data = [1, 0, 0, 0, 1, 1, 1, 0, 2, 3, 1, 0, 0, 1, 1, 1, 0]
x = 0
r = []
for n in data:
if n == 0:
if x:
r.append(x)
x = 0
r.append(n)
else:
x += n
print(r)
[1, 0, 0, 0, 3, 0, 6, 0, 0, 3, 0]
Iterate through the list and if current and next element are not 0 then add to a temp variable and put current element as 0, when the next element is zero put the value in the current element. Since, code checks for the next element with the current element, Iterate through 2nd last element and check for the last separately.
def arrange_list(arr):
value = 0
for x in range(len(arr)-1):
if arr[x] != 0:
value += arr[x]
else:
value = 0
if arr[x+1] != 0:
arr[x] = 0
else:
arr[x] = value
value = 0
if value !=0:
arr[-1] = value + arr[-1]
return arr
As Mentioned in the Comments you get to an infinite loop because of all the continues. You need to make sure that the line k=k-1 happens to avoid infinite loop.
Second why do while True and then if k==0: break change it to while k>=0.
Anyway your code won't work because it will have a problem with elements that follow a zero.
This code will work:
ans = []
tmp = 0
data = [1, 0, 0, 0, 1, 1, 1, 0]
for curr in data:
if curr != 0:
tmp += curr
elif tmp == 0:
ans.append(tmp)
else:
ans.append(tmp)
ans.append(0)
tmp = 0
print(ans)
You just need to start the value of k from 1 and set elif(data[k] != 0):. However, it will modify your original list.
data=[1, 0, 0, 0, 1, 1, 1, 0, 2, 3, 1, 0, 0, 1, 1, 1, 0]
k = 1
while True:
if(data[k-1] == 0):
pass
elif(data[k] == 0):
pass
elif(data[k] != 0):
data[k] = data[k] + data[k-1]
print(data[k])
data[k-1] = 0
k = k+1
if(k == len(data)):
break
print(data)
Output
3
5
6
2
3
[1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 0, 3, 0]
Here your code is running to infinite loop as you are using continue
statement which will again start the loop from beginning.
As in your case data[k] is zero so the first elif statement is always true
and the continue statement is executing.
Because of the above reason the code k=k-1 line is always unreachable and k value is always 7 in your case. So the while loop is running infinitely.
Below is a suggested code sample which satisfies your use case.
data = [1, 0, 0, 0, 1, 1, 1, 0, 2, 3, 1, 0, 0, 1, 1, 1, 0]
k = len(data)-1
for i in range(0,k):
if(data[i]==0):
continue
if(data[i]!=0 and data[i+1]!=0):
data[i+1]=data[i]+data[i+1]
data[i]=0
print(data)
Why not do it like this:
def convert(A):
B = [0] * len(A)
partial_sum = 0
for i in range(len(A) - 1):
partial_sum += A[i]
if A[i + 1] == 0:
B[i] = partial_sum
partial_sum = 0
if A[-1] != 0:
B[-1] = partial_sum + A[-1]
return B
As opposed to the previous answer, this actually preserves the length of the original array.
You could define a general reusable method which comes in hand in some cases.
Here it is, it returns a generator:
def slice_when(predicate, iterable):
i, x, size = 0, 0, len(iterable)
while i < size-1:
if predicate(iterable[i], iterable[i+1]):
yield iterable[x:i+1]
x = i + 1
i += 1
yield iterable[x:size]
Example of usage
Once you have in place this method, you can use it in this way:
data = [1, 0, 0, 0, 1, 1, 1, 0, 2, 3, 1, 0, 0, 1, 1, 1, 0]
test_method = slice_when(lambda _, y: y==0, data)
list(test_method)
#=> [[1], [0], [0], [0, 1, 1, 1], [0, 2, 3, 1], [0], [0, 1, 1, 1], [0]]
Your case
This is how to apply it for solving your point:
res = []
for e in slice_when(lambda _, y: y==0, data):
res += [0]*(len(e)-1) + [sum(e)]
res
#=> [1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 0, 3, 0]

Counting and summing list elements, in sections separated by three or more zeros

I have a list of integers which I want to separate according to a certain condition. I want to get the sum and the count of the list elements, stopping when three or more consecutive elements are equal to 0; then the sum and count orders restart again from where they stopped.
For example, part of the list is:
[8, 2, 1, 1, 2, 0, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 8, 0, 0, 2, 0, 0, 0, 6, 0, 0]
The process would be:
8, 2, 1, 1, 2 -> sum: 14, length: 5
0, 0, 0, 0, 0
6, 0, 2 -> sum: 8, length: 3
0, 0, 0
8, 0, 0, 2 -> sum: 10, length: 4
0, 0, 0
6, 0, 0 -> sum: 6, length: 3
So the output I want is:
[[14, 5], [8, 3], [10, 4], [6, 3]]
What I've written so far computes the sum okay, but my problem is that zeros within sections aren't counted in the lengths.
Current (incorrect) output:
[[14, 5], [8, 2], [10, 2], [6, 2]]
Code:
arr = [8, 2, 1, 1, 2, 0, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 8, 0, 0, 2, 0, 0, 0, 6, 0, 0]
result = []
summed, count = 0, 0
for i in range(0, len(arr) - 2):
el, el1, el2 = arr[i], arr[i + 1], arr[i + 2]
if el != 0:
summed = summed + el
count = count + 1
if el == 0 and el1 == 0 and el2 == 0:
if summed != 0:
result.append([summed, count])
summed = 0
count = 0
elif i == len(arr) - 3:
summed = el + el1 + el2
count = count + 1
result.append([summed, count])
break
print(result)
It is quite hard to understand what your code does. Working with Strings seems more straightforward and readable, your output can be achieved in just two lines (thanks to #CrazyChucky for the improvement):
import re
arr = [8, 2, 1, 1, 2, 0, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 8, 0, 0, 2, 0, 0, 0, 6, 0, 0]
# Convert to String by joining integers, and split into substrings, the separator being three zeros or more
strings = re.split(r'0{3,}', ''.join(str(i) for i in arr))
# Sums and counts using list comprehensions
output = [[sum(int(x) for x in substring), len(substring)] for substring in strings]
Output:
>>>output
>>>[[14, 5], [8, 3], [10, 4], [6, 3]]
Remember that readability is always the most important factor in any code. One should read your code for the first time and understand how it works.
If the full list contains numbers with more than one digit, you can do the following:
# Convert to String by joining integers, seperating them by a commade, and split into substrings, the separator being three zeros or more
strings = re.split(r',?(?:0,){3,}', ','.join(str(i) for i in arr))
# Make a list of numbers from those strings
num_lists = [string.split(',') for string in strings]
# # Sums and counts using list comprehensions
output = [[sum(int(x) for x in num_list), len(num_list)] for num_list in num_lists]
This answer is not so much to suggest a way I'd recommend doing it, as to highlight how clever Paul Lemarchand's idea of using a regular expression is. Without Python's re module doing the heavy lifting for you, you have to either look ahead to see how many zeros are coming (as in Prakash Dahal's answer), or keep track of how many zeros you've seen as you go. I think this implementation of the latter is about the simplest and shortest way you could solve this problem "from scratch":
input_list = [8, 2, 1, 1, 2, 0, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 8, 0, 0, 2, 0, 0,
0, 6, 0, 0]
output_list = []
current_run = []
pending_zeros = 0
for num in input_list:
# If the number is 0, increment the number of "pending" zeros. (We
# don't know yet if they're part of a separating chunk or not.)
if num == 0:
pending_zeros += 1
# If this is the first nonzero after three or more zeros, process
# the existing run and start over from the current number.
elif pending_zeros >= 3:
output_list.append((sum(current_run), len(current_run)))
current_run = [num]
pending_zeros = 0
# Otherwise, the pending zeros (if any) should be included in the
# current run. Add them, and then the current number.
else:
current_run += [0] * pending_zeros
current_run.append(num)
pending_zeros = 0
# Once we're done looping, there will still be a run of numbers in the
# buffer (assuming the list had any nonzeros at all). It may have
# pending zeros at the end, too. Include the zeros if there are 2 or
# fewer, then process.
if current_run:
if pending_zeros <= 2:
current_run += [0] * pending_zeros
output_list.append((sum(current_run), len(current_run)))
print(output_list)
[(14, 5), (8, 3), (10, 4), (6, 3)]
One note: I made each entry in the list a tuple rather than a list. Tuples and lists have a lot of overlap, and in this case either would probably work perfectly well... but a tuple is a more idiomatic choice for an immutable data structure that will always be the same length, in which each position refers to something different. (In other words, it's not a list of equivalent items, but rather a well-defined combination of (sum, length).)
Use this:
a = [8, 2, 1, 1, 2, 0, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 8, 0, 0, 2, 0, 0, 0, 6, 0,0]
total_list = []
i = 0
sum_int = 0
count_int = 0
for ind, ele in enumerate(a):
if ind < (len(a) - 2):
sum_int += ele
if sum_int != 0:
count_int += 1
if (a[ind] == 0) and (a[ind+1] == 0) and (a[ind+2] == 0):
if sum_int != 0:
count_int -= 1
total_list.append([sum_int, count_int])
sum_int = 0
count_int = 0
else:
sum_int += ele
count_int += 1
if sum_int != 0:
total_list.append([sum_int, count_int+1])
sum_int = 0
count_int = 0
print(total_list)

How to set n consecutive elements with a non-zero cumulative sum to one and the rest to zero in numpy?

I have a 1D numpy array of 1's and 0's. I need to change it to an array according to these conditions.
If the number of 0's between two 1's is less than 3, all of those 0's should be set to 1.
In the resulting array, if the number of consecutive 1's are less than 4, all of those 1's should be set to 0.
i.e if my array is
[0,1,1,1,0,0,0,1,1,0,0,1,1,0,0,0,0,1,0]
it should be changed to
[0,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,0,1,0]
and then to
[0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0]
I have tried using moving average to no avail. How do I write a general function, preferably with n instead of 3 and m instead of 4?
If you use core Python?
l = [0,1,1,1,0,0,0,1,1,0,0,1,1,0,0,0,0,1,0]
def split(l):
res = []
subres = [l[0]]
for i in range(len(l) - 1):
if l[i] == l[i + 1]:
subres.append(l[i + 1])
else:
res.append(subres)
subres = [l[i + 1]]
res.append(subres)
return(res)
def setall(l, val):
for i in range(len(l)):
l[i] = val
return(l)
def recode(l, changeval, replaceval, lenlimit):
for i in range(len(l) - 1):
el = l[i + 1]
if (el[0] == changeval) & (len(el) < lenlimit) & (i < (len(l) - 2)):
el = setall(el, replaceval)
l[i + 1] = el
return(l)
def flatten(l):
res = []
for el in l:
res.extend(el)
return(res)
# starting list
print(l)
# step 1
want1 = split(l)
want1 = flatten(recode(want1, 0, 1, 3))
print(want1)
# step 2
want2 = split(want1)
want2 = flatten(recode(want2, 1, 0, 4))
print(want2)
#[0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0]
#[0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0]
#[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]

Flip bits in array using python

You are given an integer array with N elements: d[0], d[1], ... d[N - 1].
You can perform AT MOST one move on the array: choose any two integers [L, R], and flip all the elements between (and including) the L-th and R-th bits. L and R represent the left-most and right-most index of the bits marking the boundaries of the segment which you have decided to flip.
What is the maximum number of 1-bits (indicated by S) which you can obtain in the final bit-string?
'Flipping' a bit means, that a 0 is transformed to a 1 and a 1 is transformed to a 0 (0->1,1->0).
Input Format: An integer N, next line contains the N bits, separated by spaces: d[0] d[1] ... d[N - 1]
Output: S
Constraints:
1 <= N <= 100000,
d[i] can only be 0 or 1 ,
0 <= L <= R < n ,
Sample Input:
8
1 0 0 1 0 0 1 0
Sample Output: 6
Explanation:
We can get a maximum of 6 ones in the given binary array by performing either of the following operations:
Flip [1, 5] ==> 1 1 1 0 1 1 1 0
Cleaned up and made Pythonic
arr1 = [1, 0, 0, 1, 0, 0, 1, 0]
arr2 = [1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
arr3 = [0,0,0,1,1,0,1,0,1,1,0,0,1,1,1]
def maximum_ones(arr):
"""
Returns max possible number of ones after flipping a span of bit array
"""
total_one = 0
net = 0
maximum = 0
for bit in arr:
if bit:
total_one += 1
net -= 1
else:
net += 1
maximum = max(maximum, net)
if net < 0:
net = 0
return total_one + maximum
print(maximum_ones(arr1))
print(maximum_ones(arr2))
print(maximum_ones(arr3))
Output:
6
14
11
If we want the L and R indices
Not so sure about this one. It can probably be made cleaner.
arr1 = [1, 0, 0, 1, 0, 0, 1, 0]
arr2_0 = [1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
arr2_1 = [1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
arr2_2 = [1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
arr3 = [0,0,0,1,1,0,1,0,1,1,0,0,1,1,1]
def maximum_ones(arr):
"""
Returns max possible number of ones after flipping a span of bit array
and the (L,R) indices (inclusive) of such a flip
"""
total_one = 0
net = 0
maximum = 0
L = R = 0
started_flipping = False
for i, bit in enumerate(arr):
if bit:
total_one += 1
net -= 1
else:
net += 1
if not started_flipping:
started_flipping = True
L = i
if net > maximum:
maximum = net
R = i
if net < 0:
net = 0
if i < R:
L = i
return (total_one + maximum, (L,R))
print(maximum_ones(arr1))
print(maximum_ones(arr2_0))
print(maximum_ones(arr2_1))
print(maximum_ones(arr2_2))
print(maximum_ones(arr3))
Output:
(6, (1, 5))
(14, (1, 16))
(14, (2, 16))
(14, (3, 16))
(11, (0, 2))
First Iteration
Here is what I had originally, if you want to see the evolution of the thought processes. Here, I was essentially transliterating what I came up with on paper.
Essentially, we traverse the array and start flipping bits (ok, not really), keeping track of cumulative flipped zeros and cumulative flipped ones in two separate arrays along with the total flipped ones in an integer counter. If the difference between flipped ones and zeroes at a given index - the "net" - drops below zero, we 'reset' the cumulative counts back at zero at that index (but nothing else). Along the way, we also keep track of the maximum net we've achieved and the index at which that occurs. Thus, the total is simply the total 1's we've seen, plus the net at the maximum index.
arr = [1, 0, 0, 1, 0, 0, 1, 0]
total_one = 0
one_flip = [0 for _ in range(len(arr))]
zero_flip = [0 for _ in range(len(arr))]
# deal with first element of array
if arr[0]:
total_one += 1
else:
zero_flip[0] = 1
maximum = dict(index=0,value=0) #index, value
i = 1
# now deal with the rest
while i < len(arr):
# if element is 1 we definitely increment total_one, else, we definitely flip
if arr[i]:
total_one += 1
one_flip[i] = one_flip[i-1] + 1
zero_flip[i] = zero_flip[i-1]
else:
zero_flip[i] = zero_flip[i-1] + 1
one_flip[i] = one_flip[i-1]
net = zero_flip[i] - one_flip[i]
if net > 0:
if maximum['value'] < net:
maximum['value'] = net
maximum['index'] = i
else: # net == 0, we restart counting our "net"
one_flip[i] = 0
zero_flip[i] = 0
i += 1
maximum_flipped = total_one - one_flip[maximum['index']] + zero_flip[maximum['index']]
Results:
print(total_one, -one_flip[maximum['index']], zero_flip[maximum['index']] )
print(maximum_flipped)
print('________________________________________________')
print(zero_flip, arr, one_flip, sep='\n')
print('maximum index', maximum['index'])
Output:
3 -1 4
6
________________________________________________
[0, 1, 2, 2, 3, 4, 4, 5]
[1, 0, 0, 1, 0, 0, 1, 0]
[0, 0, 0, 1, 1, 1, 2, 2]
maximum index 5
if arr = [1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
6 -4 12
14
________________________________________________
[0, 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 9, 10, 10, 11, 12, 12]
[1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
[0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5]
maximum index 16
Finally, if arr = [0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1]
8 0 3
11
________________________________________________
[1, 2, 3, 3, 3, 4, 4, 5, 5, 0, 1, 2, 2, 0, 0]
[0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1]
[0, 0, 0, 1, 2, 2, 3, 3, 4, 0, 0, 0, 1, 0, 0]
maximum index 2
Great, now tear it apart, people!
Traverse the whole array. Keep a count in the following way:
Do +1 for every 0 bit encountered.
Do -1 for every 1.
If this count reaches -ve at any stage, reset it to 0. Keep track of max value of this count. Add this max_count to number of 1's in input array. This will be your answer.
Code:
arr = [1, 0, 0, 1, 0, 0, 1, 0]
# I'm taking your sample case. Take the input the way you want
count,count_max,ones = 0,0,0
for i in arr:
if i == 1:
ones += 1
count -= 1
if i == 0:
count += 1
if count_max < count:
count_max = count
if count < 0:
count = 0
print (ones + count_max)
Small and simple :)

Categories