0

There is a problem where array containing numbers is given, the statement is to find the maximum length of a sub-sequence formed from the given array such that all the elements in that sub-sequence share at least one common digit.

Now whats the catch? Well, I intended to use a dictionary b to store key as every digit and value as count so far while traversing the given array, digit by digit. I thought the maximum number in values of dictionary i.e., bigger count of a digit would be the problems answer, given that we still have a glitch that we should not count a same digit that present in ONE element of array more than one time. To overcome that glitch, I used set c.

The code function for this along with driver function written below for convinience.

def solve (a):
    b={}
    answer=1

    for i in a:
        j=i
        c=set()
        c.clear()
        while(j):
            last_digit=i%10
            if(last_digit not in b and last_digit not in c):
                b[last_digit]=1
                c.add(last_digit)
            elif(last_digit in b and last_digit not in c):
                b[last_digit]+=1
                c.add(last_digit)
                answer=max(answer,b[last_digit])
            j//=10

    return answer


a=list(map(int,input().strip().split()))
print(solve(a))

There are lot test cases concerned for this code to be correct.. One of them is input is 12 11 3 4 5, the output that code gave is 1 and expected output is 2. What gives?

  • @RoryDaulton You know, sub-array means its just like what you said: all elements in sub-array need to be consecutive, but for sub-sequence, think it of like a sub-set, you know, order wont matter. – Krishna Vamshi Chintala Jul 16 '19 at 17:50

3 Answers3

1

You have good ideas. But your code would be easier if you use the Counter object from the collections module. It is designed to do just what you are trying to do: count the number of occurrences of an item in an iterable.

This code uses a generator expression to look at each value in the list alist, uses the built-in str() function to convert that integer to a string of digits, then uses the set() built-in function to convert that to a set. As you said, this removes the duplicate digits since you want to count each digit only once per item. The Counter object then looks at these digits and counts their occurrences. The code then uses Counter's most_common method to choose the digit that occurs most (the (1) parameter returns only the single most popular digit in a list, and the 0 index takes that digit and its count out of the list) then takes the count of that digit (that's the 1 index). That count is then returned to the caller.

If you are not familiar with Counter or with generator expressions, you could do the counting yourself and use regular for loops. But this code is short and fairly clear to anyone who knows the Counter object. You could use the line in the comment to replace the following four lines, if you want brief code, but I expanded out the code to make it more clear.

from collections import Counter


def solve(alist):
    digitscount = Counter(digit for val in alist for digit in set(str(abs(val))))
    # return digitscount.most_common(1)[0][1]
    most_common_list = digitscount.most_common(1)
    most_common_item = most_common_list[0]
    most_common_count = most_common_item[1]
    return most_common_count


alist = list(map(int, input().strip().split()))
print(solve(alist))

For your example input 12 11 3 4 5, this prints the correct answer 2. Note that my code will give an error if the input is empty or contains a non-integer. This version of my code takes the absolute value of the list values, which prevents a minus (or negative) sign from being counted as a digit.

Rory Daulton
  • 21,934
  • 6
  • 42
  • 50
0

Here's my own implementation of this:

def solve(list_of_numbers):
    counts = {str(i):0 for i in range(10)}  # make a dict of placeholders 0 through 9
    longest_sequence = 0                    # store the length of the longest sequence so far
    for num in list_of_numbers:             # iterate through our list of numbers
        num_str = str(num)                  # convert number to a string (this makes "is digit present?" easier)
        for digit, ct in counts.items():    # evaluate whether each digit is present
            if digit in num_str:            # if the digit is present in this number...
                counts[digit] += 1          # ...then increment the running count of this digit
            else:                           # otherwise, we've broken the sequence...
                counts[digit] = 0           # ...so we reset the running count to 0.
            if ct > longest_sequence:       # check if we've found a new longest sequence...
                longest_sequence = ct       # ...and if so, replace the current longest sequence
    return longest_sequence[1]              # finally, return the digit that had the longest running sequence.

It uses a dict to store the running counts of each digit's consecutive occurrences - for every number, the count is incremented if the digit is present, and reset to 0 if it isn't. The longest sequence's length so far is saved in its own variable for storage.

There are a few details that your implementation, I think, is overlooking:

  1. Your code might be returning the digit that appears the most, rather than the greatest number of appearances. I'm not sure, because your code is kind of hard for me to parse, and you only gave the one test example.
  2. Try to stay away from using single-letter variable names, if you can. Notice how much more clear my code above is, since I've used full names (and, at worst, clear abbreviations like ct for "count"). This makes it much easier to debug your own code.
  3. I see what you're doing to find the digits that are present in the number, but that's a bit more verbose than the situation requires. A simpler solution, which I used, was to simply cast the number into a string and use each individual digit's character instead of its value. In your implementation, you could do something like this: c = set(int(digit) for digit in str(j))
  4. You don't seem to have anything in your code that detects when a digit is no longer present, which could lead to an incorrect result.
Green Cloak Guy
  • 23,793
  • 4
  • 33
  • 53
0

I'm having trouble understanding the original problem, but I think what you need to do is cast each item as a string if it is an int and then split out each digit.

digits = {}
    for item in thelist:
        digit[item] = []
        if len(item) > 1:
            for digit in str(item):
                digits[item].append(int(digit))

if your test case is 12 11 3 4 5 then this would produce a dictionary of {12 : [1,2], 11 : [1,1], etc}