Merge the Tools!

  • + 25 comments

    Your code is very nice, but I think that overall complexity is quite high - O(n*n) - when compared to a simpler albeit more verbose approach:

    S = raw_input()
    K =int(raw_input())
    temp = []
    len_temp = 0
    for item in S:
        len_temp += 1
        if item not in temp:
            temp.append(item)
        if len_temp == K:
            print ''.join(temp)
            temp = []
            len_temp = 0
    
    • + 1 comment
      [deleted]
      • + 0 comments

        def merge_the_tools(string, k): from collections import OrderedDict l=[] for i in range(0,len(string),k): a=string[i:i+k] l.append("".join(OrderedDict.fromkeys(a))) for j in range(0,len(l)): print(l[j])

    • + 6 comments

      Similar Approach .

      s=raw_input()
      k=int(raw_input())
      n=len(s)
      
      for x in xrange(0, n, k):
          slicedStr = s[x : x+k]
          uni =[]
          for y in slicedStr:
              if y not in uni:
                  uni.append(y)
          print ''.join(uni)
      
      • + 1 comment

        Only Two test case passed with this approach

      • + 10 comments

        My first pass used a collector list to check duplicates (and passed). I then realised you can simply check the output for duplicates as you build it. I used string concatenation over list/ join

        for i in range(0, len(string), k):
            s = ""
            for j in string[i : i + k]:
                if j in s:
                    continue
                else:
                    s += j          
            print(s)
        

        Based on other solutions you could make it even simpler

        for i in range(0, len(string), k):
            s = ""
            for j in string[i : i + k]:
                if j not in s:
                    s += j          
            print(s)
        
        • + 0 comments

          excellent

        • + 0 comments

          thanks very much in solving this query

        • + 1 comment

          excellent !! but the only drawback is time complexity

          • + 2 comments

            As far as I understand it's O(n). First for loop is O(n/k), second is O(k).

            • + 0 comments

              Yes

            • + 1 comment

              isnt it o(n^2) because of 1 for loop inside another

              • + 1 comment

                im afraid its not, thats not how o(n^2) works, since the first loop only iterates through every kth value in the list, so O(n/k) and the second loop checks for k number of characters in a string so its O(k)

                O(n/k * k) = o(n)

        • + 1 comment

          can someone explain this nested loop??

          • + 0 comments

            for each value of i a complete 'for loop' of j occurs. Like in first loop i = 0 the j will work on each value of string[0 : 0+k]. After the for loop of j finishes i will move to k as the 3rd argument in i's for loop in k which indicates the skip value and j will then loop over string[k : k+k]. This goes on till i < len(string).

            for j in string[.....], j takes each value of the string in every loop and checks below conditions. If the conditions are satisfied then j will be added to a new string 's'.

        • + 1 comment

          Here is a quick one:

          for i in range(0, len(string), k): print(''.join(set(string[i:i+k])))

          • + 0 comments

            Did this work? Because items in sets are unordered and we cannot be sure in which order they get displayed.

        • + 0 comments

          thanks for this simple explanation. helped me immensly.

        • + 0 comments

          Thanks

        • + 0 comments

          Most logical solution so far!

        • + 0 comments

          can you tell me how the line of code works for j in string[i : i + k]: because i only seen for loop with range only can anyone answer my question ?

      • + 1 comment

        Though it might work, it has two for loops ! which increases the complexity of the code to N power 2 times. :(

        Looking for a answer where it is solved simple.

        • + 0 comments

          First for loop is n/k loops then we iterate over k items in each of the n/k slices. Therefore code is O(n/k * k) = O(n)

          See avmohan's response below as well

      • + 0 comments

        **bro did the same! ** for i in range(0,len(string),k): a="".join(dict.fromkeys(string[i:i+k])) print(a)

      • + 0 comments

        thanks for the code !!!!!. bt please can u just expain the for loop .. i got bit confused in for x in xrange(0, n, k): 1 st iteration it is [0:3] 2 nd [3:6] n 3 rd [6:9] ryt ?? s[8] is not present ryt , it should give error na ?? bt it is exceuting perfectly

      • + 0 comments

        same but idk why i used this :

        def merge_the_tools(string, k): ** for i in range (len(string)//k): ss=string[i*k:i*k+k]**

    • + 3 comments

      His code is also O(n). He has nested looping but each character is touched exactly once. The outer look is executed n/k times and the inner loop k times, so total n.

      Also, in your code, the check if item not in temp would be linear on the size of temp in case of a list. The complexity of your code is O(n*k). You should use a set instead. That will reduce complexity to O(n).

      • + 1 comment

        I used list. But the problem is it gives unexpected order of elements. So we are not sure if output will be 'AB' or 'BA'. Also, it changes after every runtime.

        • + 4 comments

          You need a list as well as a set. The set for the in query, to check if we've seen this before and the list to maintain the output. Membership query is O(n) in a list, ~O(1) in a set/dict.

          Below is verbose code for the same.

          def without_repetition(t):
              s = set()
              o = []
              for c in t:
                  if c not in s:
                      s.add(c)
                      o.append(c)
              return ''.join(o)
              
          
          def main():
              s = input()
              k = int(input())
              n = len(s)
              w = k
              for t in [s[i:i+w] for i in range(0, n, w)]:
                  print(without_repetition(t))
          
          main()
          
          • + 1 comment

            The problem I am facing with this code is that, the output is not in the same order of what is expected, although repeating elements are removed.

            def merge_the_tools(string, k):
                #get list of index
                ind=[i for i in range(0,len(string)+1,k)]
                #get substrings equivalent to block size
                unsetEl=([string[ind[i]:ind[i+1]] for i in range(0,len(ind)-1)])
                setEl=[]
                #apply set funtion to each substring
                for i in unsetEl:
                    setEl.append(set(i))
                    #print data
                for i in range(len(setEl)):
                    print(''.join(setEl[i]))
            
            • + 0 comments

              A set is an unordered collection of items, and you may get different output.

          • + 0 comments

            Amazing code! Simple logic

          • + 0 comments

            I ran some tests on this code (by @v3gA92) versus the iter example that got the most votes on here so far. This code, even though it is described as "verbose", increases performance significantly over the other. In the comparison I did, straight up loops took close to 6.something ms when I fed in a large test case and had timeit() run it 1000 times. The "iter" example using "zip" that so many people voted for reduced this down to 1.something ms for a performance boost that was six-fold. But your code example above using loops, being a little "verbose" but then deploying a list comprehension in a strategic location, boosted the original by a factor of 3 decimal places with a timeit() metric on my machine that was only 689 us (micro seconds verus milliseconds). I am learning from all of these posts so I am glad people came up with these options regardless.

          • + 0 comments

            logical,readable and well illustrated.

      • + 0 comments

        if y not in uni Even though we are checking uni time,it does not produce the complexit of O(n*k). As unique can only hold a maximum of allowed string character. i.e if only capitals are allowed in string,then unique can have maximum of 26 length.For,for each letter of string(size(N)),search will cost maximum of 26 steps. so total complexity will be O(N*constant value) = O(N).

      • + 1 comment

        A set is unordered. Joining the set to recreate the string would create a different order.

        • + 1 comment

          I believe that the set is being used to check for duplicates as o is the output list.

          • + 0 comments

            You are right. Figured that out after that comment. Cheers.

    • + 2 comments

      please explain how you break the string in pair example: "AS" "AC"

      • + 0 comments

        The loop iterate over every character one by one, filling in the "temp" with unique characters. So if you have a string 'AADAAC' it will fill in 'A' then eventually 'D' and finally 'C'. Once length reaches limit k, the unique characters found are joined so you get 'ADC'.

      • + 0 comments

        import textwrap

        textwrap.wrap(string,k)

    • + 0 comments

      Awesome logic with simple code

    • + 5 comments

      Hi, I came up with this, not gonna lie, did do some google searches to get the imports. Can you comment on the time complexity as well as over all effectiveness and how I could improve it yet still maintaining readability.

      import textwrap
      from collections import OrderedDict
      def merge_the_tools(string, k):
      
          list2=[]
      #devides string into n equal parts of size k
          list1 = textwrap.wrap(string, k)
      
          for i in list1:
      #removes duplicate characters from string and append it to list 2
              list2.append("".join(OrderedDict.fromkeys(i)))
      
          for i in list2:
              print(i)
      				
      

      Thanks in advance

      • + 0 comments

        can anybody explain OrderedDict.fromkeys(i) this statement?

      • + 0 comments

        You dont need list2 and append it. just print the output in for loop itself.

      • + 0 comments

        There is no need of appending it to list and having a new loop to print. Also time complexity of this solution is O(n) which is quite good!!

        import textwrap from collections import OrderedDict

        def merge_the_tools(string, k): source_list = textwrap.wrap(string,k) for var in source_list: print("".join(OrderedDict.fromkeys(var)))

      • + 0 comments

        from collections import OrderedDict import textwrap def merge_the_tools(string, k): b=textwrap.wrap(string,k) for i in range (len(b)): print("".join(OrderedDict.fromkeys(b[i])))

        #no need to append data to list 2 it is unnecessary directly print result.
        
      • + 0 comments

        Thanks :)

    • + 0 comments

      Good approach

    • + 0 comments

      thanks for this sweet and simple solution but why mine solution isn't working def merge_the_tools(string, k): length=int(len(string)//k) l=wrap(string,length)

      for i in l:
          string_list=list(i)
          new_list_for_new_string=[]
          for c in string_list:
              if c not in new_list_for_new_string:
                  new_list_for_new_string.append(c)
          print("".join(new_list_for_new_string))
      
    • + 2 comments

      hey this is a great solution.... I adapted your code without using join() and list def merge_the_tools(string, k): div=len(string)//k subword="" l=0 for i in string: l+=1 if i not in subword: subword+=i if l == k: print(subword) subword="" l=0

      • + 0 comments

        cool!

      • + 0 comments
        1. from textwrap import wrap
        2. def merge_the_tools(string, k):
        3. l=[]
        4. l=wrap(string,k)
        5. print l

        6. for i in l:
        7. string_list=list(i)

        8. new_list_for_new_string=[]
        9. for c in i:
        10. if c not in new_list_for_new_string:
          1. new_list_for_new_string.append(c)
          2. print "".join(new_list_for_new_string)
    • + 0 comments

      thank u

    • + 1 comment

      This is beautiful code. Thank you.

    • + 0 comments

      good one

    • + 1 comment

      You don't need a list for it

      subst=''
      for i in range(0,len(string)):
          if string[i] not in subst:
              subst=subst+string[i]  
          if (i+1)%k==0:
              print(subst)
              subst=''
      
      • + 0 comments

        best code the approch im looking for same idea just not clear where if and was using two loops thanks good skills

    • + 0 comments

      This is the best solution. Just using core python keywords with O(n) runtime

    • + 0 comments

      I believe this answer would be slightly more Pythonic because it doesn't track the index manually like in the above solution.

      def merge_the_tools(S, K): temp = [] for i, letter in enumerate(S): if letter not in temp: temp.append(letter) if i in range(K-1,len(S),K): print(''.join(temp)) temp = []

      merge_the_tools("AABCAAADA", 3)

    • + 0 comments

      Simple, yet affective. Congrats!

    • + 0 comments

      i have writen similar code but i seperated strings of length k it isO(n*n) but ur logic is super

    • + 0 comments

      You are using the expression

      if item not in temp

      with temp defined as type list

      That's not very efficient - it requires a list scan. If you use a set, it will have O(1) hash key lookup

    • + 0 comments

      well this one also has a high complexity coz of using that "in" keyword on a "list" use dictionary instead. :)

    • + 0 comments

      I really love your code

    • + 0 comments

      why append, just simply concat:

      def merge_the_tools(string, k):

          for i in range(0,len(string),k):
          fill(string[i:i+k])
      

      def fill(s):

      f = ''
      for r in range(len(s)):
          if s[r] in f:
              continue
          else:
              f = f + s[r]
      
      print(f)
      
    • + 0 comments

      You can replace temp = [] with empty string "" then use temp += in the for loop.

    • + 0 comments

      why these brilliant algorithms don't come to my brain -_-

    • + 0 comments

      I have tried exactly this and is quite simple for beginners to understand