На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: RaD
  
    > Python Logic Puzzle , Решение логических задач, проверка условия
      Здравствуйте. Прошу помочь с проверкой условий к логической задачи Эйнштейна на python. Вот условие задачи.

      You will write code to solve the following logic puzzle:

      1. The person who arrived on Wednesday bought the laptop.
      2. The programmer is not Wilkes.
      3. Of the programmer and the person who bought the droid,
      one is Wilkes and the other is Hamming.
      4. The writer is not Minsky.
      5. Neither Knuth nor the person who bought the tablet is the manager.
      6. Knuth arrived the day after Simon.
      7. The person who arrived on Thursday is not the designer.
      8. The person who arrived on Friday didn't buy the tablet.
      9. The designer didn't buy the droid.
      10. Knuth arrived the day after the manager.
      11. Of the person who bought the laptop and Wilkes,
      one arrived on Monday and the other is the writer.
      12. Either the person who bought the iphone or the person who bought the tablet
      arrived on Tuesday.

      Результат должен быть в виде list на подобии ['Hamming', 'Knuth', 'Minsky', 'Simon', 'Wilkes']
      Вот как я решил эту задачку.
      ExpandedWrap disabled
        import itertools
         
        def logic_puzzle():
            "Return a list of the names of the people, in the order they arrive."
            ## your code here; you are free to define additional functions if needed
            days = Monday, Tuesday, Wednesday ,Thursday, Friday = [1, 2, 3, 4, 5]
            orderings = list(itertools.permutations(days))
            names = ['Hamming', 'Knuth', 'Minsky', 'Simon', 'Wilkes']
            return next([names[Hamming-1], names[Knuth-1], names[Minsky-1], names[Simon-1], names[Wilkes-1]]
                    for(Hamming, Knuth, Minsky, Simon, Wilkes) in orderings
                    if Knuth is Simon + 1
                    for(laptop, tablet, droid, iphone, _) in orderings
                    if laptop is Wednesday and tablet is not Friday and ((droid is Wilkes) or (droid is Hamming)) and ((tablet is Tuesday) or (iphone is Tuesday))
                    for(programmer, writer, manager, designer, _) in orderings
                    if (Wilkes is not programmer) and (writer is not Minsky) and (designer is not Thursday) and (designer is not droid) and (Knuth is manager + 1)
                    if ((Knuth is not manager) and (tablet is not manager))
                    if ((Wilkes is writer and laptop is Monday) or (Wilkes is Monday and laptop is writer))
                    if ((programmer is Wilkes and droid is Hamming) or (programmer is Hamming and droid is Wilkes))
                )
      Судя по всему я неправильно написал граничные условия. Подскажите пожалуйста где я просчитался. Большое спасибо.
        Для начала стоило перевести задачу на русский язык (просто чтобы понятнее была)

        Операторы is и is not проверяют, что слева и справа ссылки на один и тот же объект, лучше использовать == и !=. За исключением операции, которая может дать не тот результат, условия вроде написаны правильно

        Вообще, задача решена не полностью. Если полностью, то надо еще выводить, кто что купил, и кто он по профессии.

        Не думаю, что в этой задаче надо оптимизировать скорость (даже на моей довольно слабой машине результат
        выскакивает меньше чем через 5 секунд), поэтому лучше было сперва выписать все циклы, а потом строчка за строчкой выписать условия.
        Потом уже можно поднять условия, не зависящие от нижних циклов вверх
        Неправильно формируется результат.

        ExpandedWrap disabled
          import itertools
           
          def logic_puzzle():
              "Return a list of the names of the people, in the order they arrive."
              ## your code here; you are free to define additional functions if needed
              days = Monday, Tuesday, Wednesday, Thursday, Friday = range(5)
              orderings = list(itertools.permutations(days))
              d = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
              n = ['Hamming', 'Knuth', 'Minsky', 'Simon', 'Wilkes']
              p = ['programmer', 'writer', 'manager', 'designer', 'unknown']
              t = ['laptop', 'tablet', 'droid', 'iPhone', 'nothing']
              return [
                  [(d[dd],
                    n[(Hamming, Knuth, Minsky, Simon, Wilkes).index(dd)],
                    p[(programmer, writer, manager, designer, unknown).index(dd)],
                    t[(laptop, tablet, droid, iphone, nothing).index(dd)],) for dd in days]
                  for Hamming, Knuth, Minsky, Simon, Wilkes in orderings
                  for laptop, tablet, droid, iphone, nothing in orderings
                  for programmer, writer, manager, designer, unknown in orderings
                      # 1. The person who arrived on Wednesday bought the laptop.
                      if Wednesday == laptop
                      # 2. The programmer is not Wilkes.
                      if programmer != Wilkes
                      # 3. Of the programmer and the person who bought the droid,
                      # one is Wilkes and the other is Hamming.
                      if {programmer, droid} == {Wilkes, Hamming}
                      # 4. The writer is not Minsky.
                      if writer != Minsky
                      # 5. Neither Knuth nor the person who bought the tablet is the manager.
                      if Knuth != manager and tablet != manager
                      # 6. Knuth arrived the day after Simon.
                      if Knuth == Simon + 1
                      # 7. The person who arrived on Thursday is not the designer.
                      if Thursday != designer
                      # 8. The person who arrived on Friday didn't buy the tablet.
                      if Friday != tablet
                      # 9. The designer didn't buy the droid.
                      if designer != droid
                      # 10. Knuth arrived the day after the manager.
                      if Knuth == manager + 1
                      # 11. Of the person who bought the laptop and Wilkes,
                      # one arrived on Monday and the other is the writer.
                      if Monday != writer and {laptop, Wilkes} == {Monday, writer}
                      # 12. Either the person who bought the iphone or the person who
                      # bought the tablet arrived on Tuesday.
                      if Tuesday in {tablet, iphone}
                  ]
           
          for names in logic_puzzle():
              print(names)


        [('Monday', 'Wilkes', 'unknown', 'droid'),
        ('Tuesday', 'Simon', 'manager', 'iPhone'),
        ('Wednesday', 'Knuth', 'writer', 'laptop'),
        ('Thursday', 'Hamming', 'programmer', 'tablet'),
        ('Friday', 'Minsky', 'designer', 'nothing')]
          Большое спасибо за помощь. Написал немного более быстрое по скорости решение. Не верно написал условия предыдущие. Еще раз спасибо за помощь
          ExpandedWrap disabled
            import itertools
             
            def imright(h1, h2):
                "House h1 is immediately right of h2 if h1-h2 == 1."
                return h1-h2 == 1
             
            def logic_puzzle():
                "Return a list of the names of the people, in the order they arrive."
                ## your code here; you are free to define additional functions if needed
                days = Monday, Tuesday, Wednesday ,Thursday, Friday = [1, 2, 3, 4, 5]
                orderings = list(itertools.permutations(days))
                names = ['Hamming', 'Knuth', 'Minsky', 'Simon', 'Wilkes']
                result = next([Hamming, Knuth, Minsky, Simon, Wilkes]
                        for(Hamming, Knuth, Minsky, Simon, Wilkes) in orderings
                        if imright(Knuth, Simon)
                        for(laptop, tablet, droid, iphone, _) in orderings
                        if laptop is Wednesday and tablet is not Friday and ((droid is Wilkes) or (droid is Hamming)) and ((tablet is Tuesday) or (iphone is Tuesday))
                        for(programmer, writer, manager, designer, _) in orderings
                        if (Wilkes is not programmer) and (writer is not Minsky) and (designer is not Thursday) and (designer is not droid) and imright(Knuth, manager)
                        if ((Knuth is not manager) and (tablet is not manager))
                        if ((Wilkes is writer and laptop is Monday) or (Wilkes is Monday and laptop is writer))
                        if ((programmer is Wilkes and droid is Hamming) or (programmer is Hamming and droid is Wilkes))
                    )
                output = [0,0,0,0,0]
                for i in range(5):
                    output[result[i]-1] = names[i]
                return output
            Я переставлять условия не стал. Как уже писал, у меня на старом Celeron 1200 ответ выскакивает уже через 5 секунд. Для одноразовой задачи более чем достаточно.

            Ответ соответствует?
            ['Wilkes', 'Simon', 'Knuth', 'Hamming', 'Minsky']
              Да, соответствует. С перестановками просто меньше прогонов будет. И ответ можно получить за секунду.
              Цитата amk @
              Для одноразовой задачи более чем достаточно.
              Вы правы. Просто хотелось повысить производительность вот и от нечего делать посидел над оптимизацией.
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0267 ]   [ 15 queries used ]   [ Generated: 3.05.24, 18:31 GMT ]