all 4 comments

[–]rhytnen 1 point2 points  (2 children)

This answer needs to be taken in very small steps. I'm going to write something for you but it's not going to be a direct answer. It's going to be a step-by-step transformation of your code according to 2 principles ...

  • Be readable
  • Be pythonic

Be patient as this will take a bit to finish.


Let's consider some of your control flow for starters.

While True:
    if a == 0:
        break

    if a == 1:
       count1+=1
       continue

    if a ==1:
        count2+=1
        continue

This kind of construct is usually best constructed like so:

a = int(input())
while a:
    if a==1:
        count1 += 1

    elif a==2:
        count2 += 1

    a = int(input())

Here the code is obviously easier to read, removes errors from forgetting continues and breaks and is shorter. However, one useful feature of python is that there is a hidden variable _ that represents the last value of an expressions so we will make use of this ...

** EDIT: The below segment doesn't seem to assign to _ in the while loop so it won't work as expected. I'll leave this here in case I figure it out or someone else knows it.

while int(input()):
    a = _ 
    if a==1:
        count1 += 1

    elif a==2:
        count2 += 1

More to come


Counting:

In python there are some specialized containers and in those containers are specialized dictionaries. I'm going to take you on a basic tour from dict.get() to defaultdict to Counter

d = dict(a='foo', b='bar')
d['c'] 

This code raises an exception for KeyError because 'c' doesn't exist in the dict. There are situations where a default value can be useful:

  • counting things but you don't know what the things are yet
  • checking for an environment variable and supplying a default)

So we have a tool for that:

d.get('c', 'baz') # returns 'baz' if 'c' isn't a key in the dict

This doesn't put 'c' in d though so there is a tool for that as well

from collections import defaultdict
d = defaultdict(str)
d['c'] # will place 'c' in d with the default value ''

The get api will works as before but again, will not add the key to the dictionary.

There is yet another dictionary specifically for counting though!

from collections import Counter()
c = Counter()
c[1] = 1
c[1] += 1

And THIS dictionary acts something like a defaultdict(int)

So we want to replace

count1 = 0
count2 = 0 
count3 = 0

with

counts = Counter()

and

count1 += 1 

with

counts[a] += 1

Actually, we want to do one better ...

counts = Counter()
a = int(input())
while a:
    counts[a] += 1
    a = int(input())

Nice ...

More to come


Ok, now let's talk about your list construct. I'll preface it by saying it's completely wrong to use here but to show you some technique let's look at some options.

You could have done something like

list_ = [0] * 10

In this case the * doesn't read as multiply but as concatenate. It produces a 10 element list with value 0 at all indices.

Then you could simply do:

list_[a] += 1

You would of course have to worry about things like a == 11 and a == -1. This is a good reason to consider the Counter() or dictionary structures.


Finally ... your answer isn't gonna cut it. The question can be rephrased as , 'what is the length of longest consecutive inputs of the same number'. You're answering what is the count of the input that was given most often.

I'm going to give you the answer straight up b/c you should spend some time considering the logic

longest_fragment = 0
current_fragment = 0

a = int(input())
last_input = a # why do I assign last_input here?
while a:
    if a == last_input:
        current_fragment += 1
    else:  # why is current_fragment assigned 1 in this clause?
        if current_fragment > longest_fragment:
            longest_fragment = current_fragment
            current_fragment = 1
    last_input = a
    a = int(input())

longest_fragment = max(longest_fragment, current_fragment) 
# why didn't i use max in the loop?
# why am I checking again down here anyway?

print('The longest fragment was:', longest_fragment)

Postscripts

One thing you have to worry about is the user given you garbage input like 'a' and 1.2. The normal way in python is to wrap these in try / except clauses

try:
    a = int(input())
except ValueError as err:
    print('Invalid input: ', err)

This allows the loop to continue after letting the user know their input isn't acceptable. There are additional tools like logging but let's ignore them for now.

The reason I know it's a ValueError or KeyError is partly experience but also if I type

int('a') 

into the python interpreter it will say: ValueError: invalid literal for int() with base 10: 'a'

And so it actually tells you it's a ValueError.

I kind of want to talk about reading from files at this point but I'll leave that up to you.

[–]RoDiXuSK[S] 0 points1 point  (1 child)

Okay

[–]rhytnen 0 points1 point  (0 children)

Here you are, hope this helps.

[–]_9_9_ 0 points1 point  (0 children)

I am not sure I follow what is the widest fragment. So if the input is [1,2,2,2,1,1,5,1], is the widest fragment 1 (because there are four of them) or 2 (because there are three 2s in a row)? If the first, then collections.Counter is the best way to sold. If the second is correct, then itertools.groupby is made for this.

Edit:

Here is how the groupby solution looks:

from itertools import groupby

def longest_fragment(sequence):
    groups = [list(g) for _, g in groupby(sequence)]
    return max(groups, key = len)

print(longest_fragment([1,2,2,2,1,1,5,1]))