简体   繁体   中英

I don't know why this for loop program doesn't work (python). Solutions?

I am trying to make a program where it sorts out numbers in a range and puts them into a list if the digits are in ascending order or stay the same. I have tried this:

numbers1 = []
for count1 in range(2, 3):
  for count2 in range(0, 10):
    for count3 in range(0, 10):
      for count4 in range(0, 10):
        for count5 in range(0, 10):
          for count6 in range(0, 10):
            number = (count1,count2,count3,count4,count5,count6)
            if number[5] >= number[4]:
              if number[4] >= number[3]:
                if number[3] >= number[2]:
                  if number[2] >= number[1]:
                    if number[1] >= number[0]:
                      numbers1.append(number)

print("Done")
input()
numbers2 = []

for count1b in range(3, 8):
  for count2b in range(0, 5):
    for count3b in range(0, 7):
      for count4b in range(0, 4):
        for count5b in range(0, 3):
          for count6b in range(0, 6):
            number = (count1b,count2b,count3b,count4b,count5b,count6b)
            if number[5] >= number[4]:
              if number[4] >= number[3]:
                if number[3] >= number[2]:
                  if number[2] >= number[1]:
                    if number[1] >= number[0]:
                      numbers2.append(number)

print("Done")

but when I run it and type numbers2 into the command prompt it just returns an empty list. numbers1 returns a complete list of numbers from 200000 to 299999 that follow the rule I explained above.

From what I can work out the first part of the code is working but it seems to just skip out the second part.

Anyone know why?

The answer to your question is: The second loop has different ranges that don't satisfy the given conditions.

There's one thing you can do to get rid of the deeply nested if blocks by combining them

if number[5] >= number[4] and number[4] >= number[3] and number[3] >= number[2] and number[2] >= number[1] and number[1] >= number[0]:

Or even better

if number[5] >= number[4] >= number[3] >= number[2] >= number[1] >= number[0]:

Here is an alternative and more flexible approach for the whole task.

import itertools

def restrictions(values):
    return all(x <= y for x, y in zip(values, values[1:]))

limits = [(2, 3), (0, 10), (0, 10), (0, 10), (0, 10), (0, 10)]
ranges = [range(a, b) for a, b in limits]

all_combinations = itertools.product(*ranges)
filtered_combinations = filter(restrictions, all_combinations)
print(list(filtered_combinations))

You can alter the values in limits or you can add tuples to that list or remove them.


Example output for limits = [(2, 4), (2, 4), (2, 5)]

[(2, 2, 2), (2, 2, 3), (2, 2, 4), (2, 3, 3), (2, 3, 4), (3, 3, 3), (3, 3, 4)]

For something like this, I would look into changing the integer numbers to strings so that you can iterate over them and sort them rather than using nested for loops.

Below was my approach, breaking it up into 3 separate functions to make it a little easier to understand. The last function find_ordered_digits will return a list of all numbers that meet your criteria (digits are increasing from left to right) within a specified range.

def get_digits(number):
    digit_list = []
    number_string = str(number)
    for str_num in number_string:
        try:
            digit_list.append( int(str_num) )
        except ValueError:
            print("ValueError: get_digits can only accept type int")
            digit_list = 0
            break
    return digit_list

def are_digits_ordered(num_list):
    if num_list == sorted(num_list):
        return True
    else:
        return False

def find_ordered_digits(start, end):
    ordered_digit_nums = []
    for num in list( range(start, end + 1) ):
        if are_digits_ordered( get_digits(num) ):
            ordered_digit_nums.append(num)
    return ordered_digit_nums

print(get_digits(387495820))
print(get_digits(239.1))

print (are_digits_ordered(get_digits(1234)))
print (are_digits_ordered(get_digits(1294)))

print (find_ordered_digits(1000, 1200))

Output:

[3, 8, 7, 4, 9, 5, 8, 2, 0]
ValueError: get_digits can only accept type int
0
True
False
[1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1122, 1123, 1124,             
1125, 1126, 1127, 1128, 1129, 1133, 1134, 1135, 1136, 1137, 1138, 1139,     
1144, 1145, 1146, 1147, 1148, 1149, 1155, 1156, 1157, 1158, 1159, 1166, 
1167, 1168, 1169, 1177, 1178, 1179, 1188, 1189, 1199]

I've intentionally written this in a slightly verbose and explicit way to make it more obvious what's going on, and to make it more flexible. It could definitely be condensed a lot and it could be a good exercise to try to rewrite it to be as short as possible. Matthias' answer is a lot more concise and efficient and I would say more in the Python style, and is also more specific.

Lastly, I'm not sure the nested for loops you are using are doing what you're expecting them to. Try adding some more print() statements in your code to see what is actually going on. For instance try adding the following before the if statements:

print(count6b)
print(count5b)

And look at the ouput.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM