1. Python / Говнокод #14505

    −99

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    for i in range(0,len(m)):
        if i==0:
            f=False
            s += x[m[i]]
        else:
            if i==len(m)-1:
                if not f:
                    f=False
                    s += ',' + x[m[i]]
                else:
                    f=False
                    s += x[m[i]]
                break
            else:
                if m[i]-m[i-1]==1:
                    if m[i+1]-m[i]==1:
                        if not f:
                            f=True
                            s += '-'
                            continue
                        else:
                            continue
                    else:
                        if not f:
                            f=False
                            s += ',' + x[m[i]]
                        else:
                            f=False
                            s += x[m[i]]
                else:
                    f=False
                    s += ','+x[m[i]]

    Была задача: на вход(m) подается массив чисел, например [1,3,5,6,7], а на выходе получаем человекочитаемую строку(s) "пн,ср,пт-вс"
    Вышло такое из меня пару месяцев назад, теперь я никогда не смогу в нем разобраться х_х

    Запостил: MAaxim91, 05 Февраля 2014

    Комментарии (82) RSS

    • Не намного проще...
      http://ideone.com/GOA8ce
      Ответить
    • massiv = [1,3,5,6,7]
      names = { 1: 'Mon', 2: 'Tue', 3: 'Wed', 4: 'Thu', 5: 'Fri',
                6: 'Sat', 7: 'Sun' }
      strings = []
                
      first = None
      for day in range(1, 9):
          if day in massiv:
              if first is None:
                  first = day
          elif first is not None:
              last = day - 1
              
              if first == last:
                  strings.append(names[first])
              else:
                  strings.append('%s-%s' % (names[first], names[last]))
              
              first = None
      
      print ','.join(strings)
      Ответить
      • [1, 2] -> Mon-Tue

        Не айс :)
        Ответить
      • Можно еще переписать так:
        massiv = [1,3,5,6,7]
        bounds = sorted(list(set(range(9)) - set(massiv)))
        periods = zip(bounds[:-1], bounds[1:])
        strings = []
        
        names = { 1: 'Mon', 2: 'Tue', 3: 'Wed', 4: 'Thu', 5: 'Fri',
                  6: 'Sat', 7: 'Sun' }
        
        for period in periods:
            first = period[0] + 1
            last = period[1] - 1
            
            if last < first:
                continue
            
            if first == last:
                strings.append(names[first])
            else:
                strings.append('%s-%s' % (names[first], names[last]))
        
        print ','.join(strings)
        Ответить
    • Мои пять копеек: http://ideone.com/nGkYh1
      Ответить
    • У меня была мысль переписать в функционально-стэковом стиле, но Путхона я не знаю, а учить лень.
      Ответить
    • (defun format-intervals (days)
        (labels ((%subscript->day (subscript)
                   (typecase subscript
                     (boolean subscript)
                     (otherwise
                      (aref #("Sun" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat")
                            (mod subscript 7))))))
          (format
           nil "~{~@[~*~a-~]~a~^, ~}"
           (mapcar #'%subscript->day
                   (iter
                     (with chunk := nil)
                     (for (pday day) :on days)
                     (cond
                       ((null day)
                        (when chunk (nconcing (cons t chunk))))
                       ((= 1 (- day pday))
                        (setf chunk (list (if chunk (car chunk) pday) day)))
                       (t
                        (when chunk
                          (nconcing (cons t chunk))
                          (setf chunk nil))
                        (nconcing (list nil pday)))))))))
      
      ;; (format-intervals '(1 3 5 6 7))
      ;; "Mon, Wed, Fri-Sun"
      %)
      Ответить
    • Присоединюсь:
      def list2ranges(lst):
          i, j = 0, 0
          res = []
          while i<len(lst):
              while (j<len(lst)) and (lst[j] == (lst[i]+j-i)):
                  j += 1
              res.append(slice(lst[i], lst[j-1] + 1, 1))
              i = j
          return res
      #
      
      def formatranges(ranges,map={},sep=(',','-')):
          res = []
          for r in ranges:
              if (r.stop - r.start) < 3:
                  res.append( sep[0].join( map.get(n, str(n)) for n in xrange(r.start, r.stop, r.step) ) )
              else:
                  res.append( map.get(r.start, str(r.start)) + sep[1] + map.get(r.stop-1, str(r.stop-1)) )
          return sep[0].join(res)
      #
      
      r = list2ranges([1,3,5,6,7])
      print formatranges(r,{1:u'пн',2:u'вт',3:u'ср',4:u'чт',5:u'пт',6:u'сб',7:u'вс',})
      Ответить
      • >u'пн'
        Кто-то еще не знает про from __future__ import unicode_literals?

        >map={}
        Опасно, хоть и он используется только для чтения.

        Плюсанул за то, что хоть кто-то разбил на функции.
        Ответить
        • Потому и написал, что используется только для чтения. Да, конечно, можно(а иногда нужно) написать
          map=None
          а потом уже
          map = map if map is not None else dict()
          но так длиннее и несколько менее очевидно.

          >from __future__ import unicode_literals
          Это с какой версии? 2.6?
          Ответить
          • >Потому и написал, что используется только для чтения.
            Понятно тебе как автору, менее очевидно для делающего code review.

            >но так длиннее и несколько менее очевидно.
            ПИТОНОПРОБЛЕМЫ. В соседнем гк спрашивал - а нахуя вообще эту "фичу" сделали?

            >Это с какой версии? 2.6?
            Да, а что? Бер 2.5 <= еще кто-то жить не может? Уже 3.4 есть.
            Ответить
            • Не, просто я не особо слежу за изменениями, не до того.
              А третий Питон вообще больной вопрос. Надо что ли опять проверить нужные мне либы на совместимость...
              Ответить
              • >Не, просто я не особо слежу за изменениями,
                Ну ни хуя себе "изменения". Ты походу питоном нечасто пользуешься.
                Ответить
        • > хоть кто-то разбил на функции
          Я тоже разбивал, см. выше ;)

          P.S. Но у меня как-то упорото получилось...
          Ответить
      • def list_to_ranges(ranges):
            result = []
            group = None
            for start, end in zip(ranges, ranges[1:]):
                if end - start > 1:
                    if group:
                        result.append(group)
                        group = None
                    result.append([start])
                elif group: group = [group[0], end]
                else: group = [start]
            if group: result.append(group)
            return result

        С одним циклом и минимумом математики.
        Ответить
        • >>> list_to_ranges([1,2,3,6,7])
          [[1, 3], [3], [6]]

          Wut?
          >>> list_to_ranges([5,6,7,1,2])
          [[5, 2]]

          Такого, правда, в исходной задаче не было, но все равно нехорошо.
          Ответить
          • Упс...
            Ответить
          • def list_to_ranges(ranges):
                result = []
                group = None
                rem = None
                for start, end in zip(ranges, ranges[1:]):
                    if end - start > 1:
                        if group:
                            result.append(group)
                            group = None
                        else:
                            result.append([start])
                            rem = end
                    elif group: group = [group[0], end]
                    else: group = [start, end]
                if group: result.append(group)
                if rem: result.append([rem])
                return result

            Получается очень многословно... жаль, что в Питоне нельзя со списками как со списками работать, можно было бы по типу хаскелевского варианта груп-бай организовать.
            Ответить
            • Ммм, что значит "со списками как со списками"? Следующий/предыдущий элемент?
              Ответить
              • Получить ссылку на часть списка, при этом не создавая нового.
                Ответить
                • Как-то так?
                  >>> a = [1,2,3,4]
                  >>> a
                  [1, 2, 3, 4]
                  >>> a[1:2] = [5,6]
                  >>> a
                  [1, 5, 6, 3, 4]
                  >>> a[1:4] = []
                  >>> a
                  [1, 4]
                  >>> a[1:1] = [42]
                  >>> a
                  [1, 42, 4]
                  Или нужно поработать именно как со связным списком аля head + tail?
                  Ответить
                  • Да нет, это все создание новых списков и замена ими частей старых. Буду проще, нужен аналог cdr.
                    Ответить
                    • Ну можно слепить франкенштейна из туплов, благо в питоне динамическая тупизация :)
                      def cons(a, b):
                          return (a, b)
                      
                      def car(a):
                          return a[0]
                      
                      def cdr(a):
                          return a[1]
                      Ответить
                      • И при этом потерять все стандартныe функции работающие со списками, итерацию, и другие синтаксические примочки...
                        Ответить
                        • А кстати не факт. Если итератор сделать к этой штуке - половина сахара типа for и list compherensions должна заработать и на таком представлении списков. Ну если я не туплю. А функции в любом случае переписывать.
                          Ответить
                          • P.S. А ну хотя, те же comprehensions вернут не тот тип, который хотелось бы ;(
                            Ответить
                            • class cons(tuple):
                                  def __init__(self, args):
                                      car, cdr = args
                                      super(cons, self).__init__(self, (car, cdr))
                                  def __len__(self):
                                      return 1 + len(self[1])
                                  @property
                                  def car(self):
                                      return self[0]
                                  @property
                                  def cdr(self):
                                      return self[1]
                                  @staticmethod
                                  def list(*args):
                                      if not args: return cons.nil
                                      else: return cons((args[0], cons.list(*args[1:])))
                                  @staticmethod
                                  def to_string(conses):
                                      return "<" + " ".join(map(str, list(conses))) + ">"
                                  def __str__(self):
                                      return cons.to_string(self)
                                  def __iter__(self):
                                      class ConsIter(object):
                                          def __init__(self, target):
                                              self.target = target
                                          def __iter__(self):
                                              return self
                                          def next(self):
                                              if self.target == cons.nil: raise StopIteration
                                              else:
                                                  result = self.target[0]
                                                  self.target = self.target[1]
                                                  return result
                                      return ConsIter(self)
                              
                              class nil(cons):
                                  def __init__(self):
                                      pass
                                  def __len__(self):
                                      return 0
                              
                              cons.nil = nil()

                              Что с людьми делают выходные...
                              ЗЫ. Получился список из Схемы, вместо КЛ, но уж так и быть.
                              Ответить
    • Нахуй лабу.
      Ответить
    • Поучаствую в специальной олимпиаде:
      http://ideone.com/vJcu8x
      import Data.List
      weak_days = [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" ]
      
      groupBy' _ [] = []
      groupBy' cmp l = reverse $ map reverse $ foldl (accumulateGroups cmp) [] l where
      	lastGroupsPick cmp (x:xs) i = if cmp x i then [i:x:xs] else [i]:[x:xs]
      	accumulateGroups cmp [] i = [[i]]
      	accumulateGroups cmp (g:gs) i = (lastGroupsPick cmp g i) ++ gs
      
      day_of_week_converter l = intercalate ", " $ map strItem $ groupBy' (\f n -> f+1==n) $ nub $ sort l where
      	strItem [] = []
      	strItem [i] = weak_days!!i
      	strItem [i, j] = weak_days!!(i-1)++", "++weak_days!!(j-1)
      	strItem (i:is) = weak_days!!(i-1)++"-"++weak_days!!(last is - 1)
      
      main = mapM_ (print . day_of_week_converter) l where
      	l = [[], [2], [1,2], [1,2,4], [1,3,5,6,7], [1,2,3,4,5,6,7], [2,3,4,4,6,7,1]]

      Но почему мне пришлось на большую часть этого кода писать реализацию стандартной функции groupBy? Аж 5 строк. Почему стандартный groupBy из стандартный библиотеки требует выполнения условия транзитивности для элементов группы? Наверное дофига оптимизаторы.
      Ответить
      • Чужой код добавлю (автор не зарегистрирован) с комментариями автора:
        https://ideone.com/uJl0ix
        # your code goes here
        arrayNumbers=[1,3,4,7]
        arraySubstitution=["1","2","3","4","5","6","7"]
        result=str(arrayNumbers[0])
        f=False
        for i in range(1,len(arrayNumbers)):
        	if ((arrayNumbers[i-1]+1)!=arrayNumbers[i]):
        		if f==True:
        			result+=str(arraySubstitution[arrayNumbers[i-1]-1])+","+str(arraySubstitution[arrayNumbers[i]-1])
        			f=False
        		else: result+=","+str(arraySubstitution[arrayNumbers[i]-1])
        	else:
        		if result[len(result)-1]!="-":result+="-"
        		f=True
        if f==True:	result+=str(arraySubstitution[arrayNumbers[len(arrayNumbers)-1]-1])
        print(result)

        myaut вот этот питушек память не желеет
        Ответить
        • Я:
          > if f==True:
          Кстати насколько это адекватно для питона?

          Автор:
          вполне
          Ответить
          • Да, в питоне такой булшит особенно забавен, потому что если человек хотел проверить именно на True, а не истинность, то оно таки не сработает как надо. Тут нужен is. А в противном случае классика булшита =)
            Ответить
            • что ты имеешь в виду? Объясни пожалуйста.
              Ответить
              • Действительно, что? Скажем, в 2.6 наблюдаю такое:
                >>> 3 is True
                False
                >>> 3 == True
                False
                >>> [1] is True
                False
                >>> [1] == True
                False
                >>> not not 3
                True
                >>> not not [1]
                True

                Моих знаний питона не хватает, чтобы различить == и is.
                Ответить
                • print(3==True)
                  print(3==False)
                  print(3 is True)
                  print(3 is False)
                  https://ideone.com/PAEJrD
                  И что не так?
                  В 3 теперь нельзя писать True = False
                  Ответить
                  • > И что не так?
                    А я и не знаю, что не так, я не питонист, просто прочитал в комментарии про "is", посмотрел, что он на моих примерах не отличается от ==, и теперь мне, как и верхнему гостю, хочется узнать, что хотел сказать автор.
                    Ответить
                • 1 == True даёт True, 1 is True даёт False. Та же фигня с 0 и False.
                  По-крайней мере на втором питоне.
                  Ответить
      • В моём коде выше ошибка в строке 12:
        strItem [i] = weak_days!!i

        надо заменить на
        strItem [i] = weak_days!!(i-1)


        Довольно жалко, что пришлось реализовывать заново стандартную функцию, кода бы меньше было. Главное об этой особенности стандартной функции нигде не сказано что она не работает адекватно в подобных случаях. Хоть бы требование вписали к предикату.
        import Data.List
        weak_days = [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" ]
        day_of_week_converter l = intercalate ", " $ map strItem $ groupBy (\f n -> f+1==n) $ nub $ sort l where
        	strItem [] = []
        	strItem [i] = weak_days!!(i-1)
        	strItem [i, j] = weak_days!!(i-1)++", "++weak_days!!(j-1)
        	strItem (i:is) = weak_days!!(i-1)++"-"++weak_days!!(last is - 1)
        main = mapM_ (print . day_of_week_converter) l where
        	l = [[], [2], [1,2], [1,2,4], [1,3,5,6,7], [1,2,3,4,5,6,7], [2,3,4,4,6,7,1]]

        http://ideone.com/LelJ7Q
        Ответить
        • > Хоть бы требование вписали к предикату.
          Ага, странная она. Сравнивает с первым элементом группы, а не с предыдущим. Об этом стоило бы написать в доке.
          Ответить
      • > weak_days
        Слабые дни... Женский календарь что ли? :)
        Ответить
    • А чем я хуже?

      http://ideone.com/05JzkM
      Ответить
      • Если подать {0, 1, 2, 3, 5, 6, 7}, то выдает "er - ср, "
        Ну и пары дней выдает как интервал =)
        Ответить
        • и правильно выдает, ибо входной массив - хуйня. Сунул хуйню - получил хуйню

          0 - это терминатор. Можно вместо терминатора проверять на конец массива.
          Ответить
          • > 0 - это терминатор
            {1, 2, 5, 6, 7, 0, 7, 3, 4, 5} >>> "пн - вт, пт - вс, er, вс,"
            Так что 0 тут работает не как терминатор, а как еще один элемент.
            Это просто функция не выводит последний элемент получившегося списка. :)
            Ответить
            • Ну или так) Можно добавить проверку, но оно и так неплохо работает. Спасибо за внимание!)
              Ответить
    • week = ['Mon','Tue','Wed','Thu','Fri','Sat', 'Sun']
      nums = [1,3,5,6,7]
      
      def shadow(mask):
      	yield 1
      	while mask > 1:
      		yield int(mask % 8 != 7)
      		mask //= 2
      
      bm = list(int(i in nums) for i in xrange(1, 8))
      sm = list(shadow(int(''.join(map(str, bm)), 2)))[::-1]
      
      print ''.join(('!,-!'[2*b+s],week[i])[b*s] for (i,(b,s)) in enumerate(zip(bm,sm)))
      Ответить
    • В моём примере выше есть ошибка, но идея проверять делимость на 2^3 красивая :)
      Вот так вроде всё правильно работает:

      import re
      
      week = ['Mon','Tue','Wed','Thu','Fri','Sat', 'Sun']
      nums = [1,3,5,6,7]
      
      repl = [('[!]{2,}', ','), ('![\w]{3}!', '-'), ('!', ',')]
      s = '!'.join(('', week[i-1])[i in nums] for i in xrange(1,8))
      s = reduce(lambda s,i: re.sub(repl[i][0], repl[i][1], s), xrange(3), s)
      
      print s
      Ответить
    • И, наконец, самый лаконичный вариант:

      import re
      
      week = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat','Sun')
      nums = (1,3,5,6,7)
      
      repl = (('[!]{2,}', ','), ('![\w]{3}!', '-'), ('!', ','))
      s = '!'.join(('',week[i])[i in nums] for i in xrange(1,8))
      s = reduce(lambda s,r: re.sub(*r,string=s), repl, s)
      
      print s
      Ответить
    • И ещё немного грамотнее, и в одну строку дня пущего эффекта :)
      import re
      week = ('Mon','Tue','Wed','Thu','Fri','Sat','Sun')
      nums = (1,3,5,6,7)
      
      print reduce(lambda s,r: re.sub(*r,string=s), ((';{2,}',','),(';\w{3};','-'),(';', ',')), ';'.join(('',day)[i in nums] for i,day in enumerate(week,1)))
      Ответить
      • хуйня какаято
        >>> nums = (1,2,3,4,5,6,7)
        >>> print reduce(lambda s,r: re.sub(*r,string=s), ((';{2,}',','),(';\w{3};','-'),(';', ',')), ';'.join(('',day)[i in nums] for i,day in enumerate(week,1)))
        Mon-Wed-Fri-Sun
        Ответить
    • http://ideone.com/nvlWwn
      Ответить
    • Простите, я опоздал на олимпиаду на четыре года:
      from collections import defaultdict as d
      
      days = d(lambda: "??", {1: "пн", 2: "вт", 3: "ср", 4: "чт", 5: "пт", 6: "сб", 7: "вс"})
      
      def f(x):
          stack = []
          state = 0
          for i in x:
              if 0 == state:
                  stack.append(i)
                  state = 1
              elif 1 == state:
                  if 1 == i - stack[-1]:
                      state = 2
                      stack.append([stack.pop(), i])
                  else:
                      state = 1
                      stack[-1] = days[stack[-1]]
                      stack.append(i)
              elif 2 == state:
                  if 1 == i - stack[-1][1]:
                      state = 3
                      stack[-1][1] = i
                  else:
                      state = 1
                      a, b = stack.pop()
                      stack += [days[a], days[b]]
                      stack.append(i)
              elif 3 == state:
                  if 1 == i - stack[-1][1]:
                      state = 3
                      stack[-1][1] = i
                  else:
                      state = 1
                      stack[-1] = days[stack[-1][0]] + '-' + days[stack[-1][1]]
                      stack.append(i)
          if 1 == state:
              stack[-1] = days[stack[-1]]
          elif state == 2:
              a, b = stack.pop()
              stack += [days[a], days[b]]
          elif state == 3:
              stack[-1] = days[stack[-1][0]] + '-' + days[stack[-1][1]]
          return ", ".join(stack)
      
      tests = (
          (1,2,3,6,7),
          (1,3,5,7),
          (1,2,3,4,5,6,7),
          (1,2,3,4,6),
          (1,2,4,5,7),
          (1,2,8,9,10,4,5,6,6),
      )
      
      print(*list(map(lambda x: str(x) + ' → ' + str(f(x)), tests)), sep = "\n")
      Ответить
    • Кто последний в очереди?
      def list2days(m):
          days = ('день программиста', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб', 'вс')
          chunks = []
          buf = []
          m = sorted(filter(lambda x: 1 <= x <= 7, set(m)))
          for x in m:
              if len(buf) == 0:
                  buf += [x]
              elif x - buf[-1] == 1:
                  buf += [x]
              else:
                  chunks += [buf]
                  buf = [x]
          if len(buf) > 0:
              chunks += [buf]
      
          res = ''
          for chunk in chunks:
              res += f',{days[chunk[0]]}'
              l = len(chunk)
              if l == 2:
                  res += f',{days[chunk[1]]}'
              elif l > 2:
                  res += f'-{days[chunk[-1]]}'
          return res[1:] if len(res) > 0 else ''
                      
      
      def main():
          tests = (
              ((1, 3, 5,6,7), 'пн,ср,пт-вс'),
              ((1, 2, 5,6,7), 'пн,вт,пт-вс'),
              ((1,2,3,4,5,6,7), 'пн-вс'),
              ((1,2,3, 5,6,7), 'пн-ср,пт-вс'),
              ((5, 2, 7, 1), 'пн,вт,пт,вс'),
              ((1,2,3, 7), 'пн-ср,вс'),
              ((1, 3,4,5,6,7), 'пн,ср-вс'),
              ((), ''),
              ((2,), 'вт'),
              ((1, 2), 'пн,вт'),
              ((1, 2, 4), 'пн,вт,чт'),
              ((2, 3, 4, 4, 6, 7, 1), 'пн-чт,сб,вс')
          )
          for test in tests:
              res = list2days(test[0])
              print(f'{test[0]} -> {res}', 'OK' if res == test[1] else f'FAIL: {test[1]}')
          
      if __name__ == '__main__':
          main()
      Ответить
    • -- https://ideone.com/RClG9U
      import Data.List
      
      fmt :: [Int] -> String
      fmt ns = intercalate "," . map (intercalate "-" . map name) . toR . mkG uniq . split2 . partite $ uniq
        where
          uniq = nub $ sort ns
          diffs xs = if null xs then [] else 0 : zipWith (-) (tail xs) xs
          partite = map length . groupBy (curry$(==1).snd) . diffs
          split2 = (=<<) (\x -> case x of 2->[1,1]; _->[x])
          name = (!!) ["вс","пн","вт","ср","чт","пт","сб","вс"]
          toR = map (\x -> case x of [_]->x; _->[head x, last x])
          mkG xs ks = case ks of (k:ks') -> let (ls,rs) = splitAt k xs in ls:mkG rs ks'; _ -> []
      Ответить
    • показать все, что скрытоvanished
      Ответить

    Добавить комментарий