Основная лягушка 🐸


44

«Основная лягушка» - странное животное, которое прыгает между целыми числами, пока не прибудет 3 или 19 ...


Ваша программа должна принимать целое число в nкачестве входных данных и выводить результат приведенного ниже алгоритма ( 3или 19).

Для данного целого числа n >= 2:

  1. Позвольте fбыть положением лягушки. Первоначально установлено значениеn
  2. если f = 3или f = 19: лягушка перестает прыгать - остановите программу и вывод f.
  3. если fпрост: лягушка прыгает на позицию 2×f-1. Вернитесь к шагу 2.
  4. if fявляется составным: давайте dбудем fсамым большим простым делителем. Лягушка прыгает на позицию f-d. Вернитесь к шагу 2.

Примеры:

Пример с n = 5:

5 > 9 > 6 > 3 stop

Программа должна вывести 3.

Еще один пример с n = 23:

23 > 45 > 40 > 35 > 28 > 21 > 14 > 7 > 13 > 25 > 20 > 15 > 10 > 5 > 9 > 6 > 3 stop

Опять же, программа должна вывести 3.

Тестовые случаи:

10 => 3
74 => 19
94 => 3
417 => 3
991 => 19
9983 => 19

Вы можете предположить 1 < n < 1000000(я проверил, программа заканчивается для этих значений).


3
3 петли - [3 5 9 6 3], а 19 петли - [19 37 73 145 116 87 58 29 57 38 19]
Арно

8
Классная вариация Коллатца.
Артур

3
Если мы не можем доказать, что лягушка всегда приходит 3или 19, мы могли бы изменить пункт 2. в алгоритме, чтобы сказать, что если лягушка вошла в какой-либо цикл (обнаружил позицию, которую она видела ранее), то она прекращает прыжок и возвращает наименьшее член этого цикла.
Джеппе Стиг Нильсен

4
@PyRulez Если он достигнет этого, вы, вероятно, должны сказать ОП.
mbomb007

3
@KeyuGan Может быть, это было бы хорошо опубликовать на Math.SE.
mbomb007

Ответы:



12

C (gcc),  87  65 байт

i,k;f(n){for(i=n;i>1;)for(k=i;k%--i;);n=~16&n-3?f(n-k?:n+n-1):n;}

Попробуйте онлайн!

Объяснение:

i,k;
f(n)
{
    for (i=n; i>1;)              // Loop until `k` is prime (the largest positive
                                 // `i` inequal to `k` that divides `k` is 1).
        for (k=i; k%--i;);       // Find the largest factor `k`

    n =                          // Returning like this is undefined behaviour,
                                 // but happens to work with gcc. This can be
                                 // replaced with `return` at the cost of 4 bytes.

        ~16&n-3                  // If `n` is 3 or 19, this expression equals 0 and
                                 // the algorithm halts. Otherwise the function
                                 // calls itself to perform the next iteration.

        ? f(n-k ?: n+n-1)        // If `n-k` is non-zero, n is not prime.
                                 // In this case call `f` with the value of `n-k`.
                                 // (Omitting the second `n-k` between `?` and `:`
                                 // is a gcc extension)
                                 // Otherwise call `f` with `2*n-1`.

        : n;                     // All done, `n` is returned.
}

Портативная версия (72 байта):

i,k;f(n){for(i=n;i>1;)for(k=i;k%--i;);return~16&n-3?f(n-k?n-k:n+n-1):n;}

Попробуйте онлайн!

С более подходящими именами переменных:

f,r;o(g){for(f=g;f>1;)for(r=f;r%--f;);g=~16&g-3?o(g-r?:g+g-1):g;}

Попробуйте онлайн!


5
Очень люблю игру со словом лягушка и ваши переменные. +1.
rayryeng - Восстановить Монику

10

Сетчатка , 63 62 байта

Спасибо Нейлу за сохранение 1 байта.

{`^(11+)(?<!^\2+(11+))(?=\1+$)

^(?!(11+)\1+$|111$|1{19}$)1
$_

Попробуйте онлайн!

Ввод и вывод в унарном виде (набор тестов использует десятичные для удобства). Это решение становится невероятно медленным для больших входов. В 9983тестовых примерах таймаута на TIO.

объяснение

Благодаря этому {оба этапа программы просто запускаются в цикле, пока они больше не влияют на строку. Мы чередуем этапы обработки композитов и этапы обработки простых чисел. Это позволяет нам избежать фактического условия (которого на самом деле нет в Retina). Если текущее значение неверно для сцены, сцена просто ничего не делает.

^(11+)(?<!^\2+(11+))(?=\1+$)

Это обрабатывает композиты. Мы сопоставляем потенциальный делитель с (11+), но затем проверяем, что он не является составным с (?<!^\2+(11+)), поэтому мы рассматриваем только простые факторы. Из-за жадности +, это приоритетный фактор. Затем мы проверяем , что этот потенциал делитель является фактическим делителем, пытаясь соответствовать остальной части строки с повторением этого, (?=\1+$). Этот делитель просто удаляется из строки, как вы вычитаете что-то в унарном виде.

^(?!(11+)\1+$|111$|1{19}$)1
$_

Это обрабатывает простые числа, кроме 3 и 19 . Отрицательный взгляд гарантирует, что ввод не составной, а не 3 и не 19 . Затем мы сопоставляем один 1и заменяем его всей строкой. Это унарная форма вычисления n - 1 + n , которая, конечно, равна 2n-1 .

Как только мы нажмем 3 или 19 , ни один из этапов не сможет соответствовать строке, и она больше не будет изменена.


1
Разве не так 1$'же, как $_?
Нил

4
@Neil Да ......
Мартин Эндер

8

Шелуха , 15 байт

Ω€p57§|o←DṠ-o→p

Попробуйте онлайн!

объяснение

Ω€p57§|o←DṠ-o→p  Implicit input n.
Ω                Do this to n until
 €p57            you get a prime factor of 57 (which are 3 and 19):
            o→p   Take last element of the prime factors of n
          Ṡ-      and subtract it from n,
     §|           or if this gives 0 (so n is prime),
       o←D        double and decrement n.

8

Желе , 12 байт

_ÆfṂoḤ’$µÐḶṂ

Попробуйте онлайн!

Как это работает

_ÆfṂoḤ’$µÐḶṂ  Maink link. Argument: n

        µ     Combine the links to the left into a chain.
         ÐḶ   Repeatedly call the chain monadically until the results are no longer
              unique. Yield the loop, i.e., the first occurrence of the first
              repeated integer, up to and excluding the repetition.
              Let's call the argument of the chain k.
_Æf             Subtract all prime factors of k from k.
   Ṃ            Take the minimum of the differences. This yields 0 iff k is prime.
     Ḥ’$        Compute 2k-1.
    o           Take the logical OR of the results.
              The result is now a rotation of either [3, 5, 9, 6] or
              [19, 37, 73, 145, 116, 87, 58, 29, 57, 38].
          Ṃ   Take the minimum, yielding either 3 or 19.

7

Wolfram Language (Mathematica) , 6566 68 байтов

#//.i:Except[3|19]:>If[PrimeQ@i,2i-1,i-#&@@Last@FactorInteger@i]&
  • -1 байт, спасибо Мише Лаврову!
  • -2 байта, спасибо Мартину!

Попробуйте онлайн!

Вдохновленный совет . По сути, он просто воссоздает алгоритм.

//.есть RepeatedReplaceи /;есть Condition. Таким образом, код будет заменять i_(единичное количество) на If[PrimeQ@i,2i-1,i-#&@@Last@FactorInteger@i], пока не произойдет i!=3&&!=19оценка True.

Ориентир:

эталонный тест


3
забавный факт: этот код не будет работать для больших чисел, например, 10000000010потому чтоmaximum number of iterations is 2^16 (= 65536)
J42161217

1
Несколько более короткий способ проверки 3 и 19#//.i:Except[3|19]:>If[PrimeQ@i,2i-1,i-#&@@Last@FactorInteger@i]&
Миша Лавров

@MishaLavrov но результат неверный?
Кейу Ган

@KeyuGan Для меня две функции дают одинаковый результат для целых чисел от 1 до 1000.
Миша Лавров,

1
Возможно, проблема в том, что при копировании и вставке из комментариев вставляются непечатаемые символы, что иногда случается.
Миша Лавров

6

05AB1E , 19 18 17 байт

[ÐƵηfså#pi·<ëDfθ-

Попробуйте онлайн!

объяснение

[      #            # loop until
 Ð   så             # a copy of the current value is contained in
  Ƶηf               # the unique prime factors of 171
        pi          # if the current value is prime
          ·<        # double and decrement
            ë   -   # else subtract
             Dfθ    # the largest prime factor of a copy of the current value

4
+1 за наличие настоящей лягушки в вашем исходном коде
Арно

За 57991 более 1 минуты
РосЛюП

@RosLuP: Вам лучше запускать очень длинные тестовые случаи в автономном режиме;)
Emigna

5

JavaScript (ES6), 73 71 69 байт

f=n=>57%n?f(n-(g=(k,d=1)=>++d<k?k%d?g(k,d):g(k/d):d<n?d:1-n)(n)):n%38

Контрольные примеры

Отформатировано и прокомментировано

f = n =>                 // given n
  57 % n ?               // if n is neither 3, 19 or 57 (and assuming that n is > 1):
    f(                   //   do a recursive call to f() with:
      n -                //     n minus
      (g = (k, d = 1) => //     the result of the recursive function g():
        ++d < k ?        //       increment d; if d is less than k:
          k % d ?        //         if d is not a divisor of k:
            g(k, d)      //           recursive call to g() with k and d unchanged
          :              //         else:
            g(k / d)     //           recursive call to g() with k = k / d, d = 1
        :                //       else, d is now the highest prime divisor of n:
          d < n ?        //         if d is less than n:
            d            //           n is composite: return d, which results in f(n - d)
          :              //         else:
            1 - n        //           n is prime: return 1 - n, which results in f(2n - 1)
      )(n)               //     initial call to g()
    )                    //   end of recursive call to f()
  :                      // else:
    n % 38               //   return n % 38 (gives 19 as expected if n = 57)

1
Смарт, используя 57%nи n%38вместо n==3|n==19. Сохранено 1 байт в моем ответе на Java , так что спасибо!
Кевин Круйссен

В ideone 57991 входные данные генерируют prog.js: 2: 26 InternalError: слишком много рекурсии
RosLuP

В tio f = n => 57% n? F (n- (g = (k, d = 1) => ++ d <k? K% d? G (k, d): g (k / d) : d <n? d: 1-n) (n)): n% 38 print (f (57991)) генерировать программу остановки не выводится, как мне кажется
RosLuP

1
@RosLuP Это игра в гольф без каких-либо особых ограничений. Текущий консенсус заключается в том, что ограничения скорости или памяти (например, размер стека вызовов) могут игнорироваться, если в вопросе явно не указано иное. Я считаю само собой разумеющимся, что предел в 1000000 является просто информативным, потому что последовательность не была проверена выше этого. Между прочим, ваше 70-байтовое решение прекрасно и, вероятно, более актуально, чем 93-байтовая версия для решения задачи игры в гольф.
Арно,


4

Python 2 , 110 105 103 101 байт

-2 байта благодаря @Lynn

f=lambda n,i=2,k=0:i/n and(n*(n&~16==3)or f((2*i-1,k-i)[k>0]))or n%i and f(n,i+1,k)or f(n/i,2,k or n)

Попробуйте онлайн!


Python 2 , 116 112 105 байт

f=lambda n,i=2:i/n*i or n%i and f(n,i+1)or f(n/i)
n=input()
while~16&n-3:n=[2*n-1,n-f(n)][f(n)<n]
print n

Попробуйте онлайн!


1
…n*(n&~16==3)or…экономит 2 байта.
Линн

Для ввода 57991 sys.setrecursionlimit (20000)
RosLuP

4

MATL , 22 21 байт

Спасибо @Giuseppe за удаление 1 байта!

`tZp?Eq}tYfX>-]tI19h-

Попробуйте онлайн! Или проверьте все тестовые случаи .

объяснение

`           % Do...while
  t         %   Duplicate. Takes (implicit) input the first time
  Zp        %   Is it prime? 
  ?         %   If so
    Eq      %     Times 2, minus 1
  }         %   Else
    t       %     Duplicate
    YfX>-   %     Prime divisors, maximum, subtract
  ]         %   End
  t         %   Duplicate
  I19h      %   Push array [3 19]
  -         %   Subtract, element-wise. The result is truthy if and only if
            %   it doesn't contain any zero
            % End (implicit). Next iteraton if top of the stack is truthy
            % Display (implicit)

4

Haskell - 154 байта

f 3=3
f 19=19
f n
 |(c==[1])=f$2*n-1
 |True=f$n-head c
 where c=z n;v b=reverse[x|x<-[1..(b-1)],b`rem`x==0];z j=case v j of[1]->[1];s->filter((==[1]).v)$s

Вероятно, здесь пропущены некоторые трюки с гольфом, это моя первая попытка игры в гольф на Haskell.


Здравствуйте и добро пожаловать на сайт. Вам не нужны переводы строки и пробелы для охранников. Вы также можете использовать 1>0в Trueбольшинстве случаев, но часто может быть лучше использовать назначение, например c<-z n.
Пшеничный волшебник

1
[x|x<-[b-1,b-2..1],rem b x==0]также короток, чем reverse[x|x<-[1..(b-1)],bрем x==0].
Пшеничный волшебник

2
И последнее: если вы хотите обсудить игру в гольф на Haskell, вы можете присоединиться к нам в « Monads and Men» .
Пшеничный волшебник

3

Нейм , 17 16 байт

ͻY𝐏𝕚÷D𝐌Ξᚫ<#D𝐏𝐠𝕊

Объяснение:

ͻ                   Start infinite loop
 D                  Duplicate
  Y                 Push 57
   𝐏                Prime factors: [3 19]
     𝕚              If the second-to-top of stack is in the list
      ÷             Break the loop
       D            Duplicate
        𝐌Ξᚫ<       If prime, double and decrement
            #D𝐏𝐠𝕊   Otherwise, subtract the largest prime factor

Попробуйте онлайн!



3

Java 8, 140 135 134 94 байта

n->{for(int f,t,m=0;57%n>0;n=f>n?2*n-1:n-m)for(t=n,f=1;f++<t;)for(;t%f<1;t/=m=f);return n%38;}

5-байтное преобразование рекурсивного метода Java 7 в лямбду Java 8 с циклом.
-1 байт неявно благодаря ответу @Arnauld на JavaScript путем изменения n!=3&n!=19и return n;на 57%n>0и return n%38;.
Я думаю, что должно быть возможным как-то объединить два цикла и проверить, nявляется ли простое число, и получить его наибольший простой множитель одновременно, но я не могу понять это (пока). Так что это будет первоначальная версия на данный момент.
-40 колоссальных байтов благодаря @Nevay, делая то, что я не мог сделать: комбинировать циклы для проверки простых чисел и наибольшего простого множителя одновременно.

Объяснение:

Попробуйте это здесь (выполняется даже 999999менее чем за 1 секунду).

n->{                  // Method with integer as both parameter and return-type
  for(int f,          //  Flag-integer
          t,          //  Temp-integer
          m=1;        //  Max prime factor integer, starting at 0
      57%n>0;         //  Loop (1) as long as `n` is not 3, not 19 and not 57:
      n=f>n?          //    After every iteration: if `f` is larger than `n`:
         2*n-1        //     Change `n` to `2*n-1`
        :             //    Else:
         n-m)         //     Change `n` to `n-m`
    for(t=n,          //   Reset `t` to `n`
        f=1;          //   Reset `f` to 1
        f++<t;)       //   Inner loop (2) from 2 to `t` (inclusive)
      for(;t%f<1;     //    Inner loop (3) as long as `t` is divisible by `f`
        t/=m=f;       //     Set `m` to `f`, and set `t` to `t/f`
      );              //    End of inner loop (3)
                      //   End of inner loop (2) (implicit / single-line body)
                      //  End of loop (1) (implicit / single-line body)
  return n%38;        //  Return `n%38`, which is now either 3 or 19
}                     // End of method

1
1 символ не является полиглотом C # :(
Ян Х.

@IanH. Хе-хе, да, это обычно так: n=>вместо n->. И иногда строчные / прописные звонки. ;)
Кевин Круйссен

1
94 байта:n->{for(int f,t,m=0;57%n>0;n=f>n?2*n-1:n-m)for(t=n,f=1;f++<t;)for(;t%f<1;)t/=m=f;return n%38;}
Невай

@Nevay Спасибо! Я просто знал, что можно комбинировать петли, но не мог этого понять. Огромные 40 байтов сэкономлены благодаря вам!
Кевин Круйссен,

3

Баш, 73 байта

((57%$1))&&$0 $[(x=$1-`factor $1|sed 's/.* //'`)?x:2*$1-1]||echo $[$1%38]

Попробуйте онлайн! Немного доработан для работы на TIO.

Рекурсивно вызывает свой собственный файл сценария с помощью $0, который не работает в TIO, потому что он должен быть запущен как./filename.sh . Принимает ввод как аргумент командной строки.

Использует тот же модульный трюк, что и в ответе @ Arnauld's JS .

Тестовые случаи

$ for t in 5 23 10 74 94 417 991 9983;{ echo -n "$t -> "; ./prime-frog.sh $t; }
5 -> 3
23 -> 3
10 -> 3
74 -> 19
94 -> 3
417 -> 3
991 -> 19
9983 -> 19


1

Pyth , 19 байт

.W!/P57H?P_ZtyZ-ZeP

Проверьте все контрольные примеры!

Ответ лузги вдохновил меня , чтобы сохранить 2 байта ( ,3 19в P57).

Как это работает

.W! / P57H? P_ZtyZ-ZeP - Полная программа.

.W - Функциональное время. В то время как A (значение) верно, значение = B (значение). Возвращает последнее значение.
    P57 - простые факторы 57 ([3, 19]).
   / H - подсчитать вхождения текущего значения.
  ! - Логически НЕ. 0 -> Правда, все остальное -> Ложь.
        ? P_Z - если текущее значение простое, то:
            tyZ - удвоить текущее значение, уменьшить.
               -ZeP - иначе, вычесть максимальный простой коэффициент текущего значения из себя.
                     - Печать безоговорочно.

1

PowerShell , 150, 126 байт

for($n="$args";57%$n){$a=$n;$d=for($i=2;$a-gt1){if(!($a%$i)){$i;$a/=$i}else{$i++}};if($n-in$d){$n+=$n-1}else{$n-=$d[-1]}}$n%38

Попробуйте онлайн! (предупреждение: медленно для больших чисел)

Итерационный метод. PowerShell не имеет встроенных модулей факторизации, поэтому этот код заимствован из моего ответа на Prime Factors Buddies .

Первый наш forцикл. Настройка устанавливает $nв качестве входного значения, а условное условие поддерживает цикл, пока 57%$nон не равен нулю (спасибо Арно за этот трюк). Внутри цикла мы сначала получаем список простых факторов $a(установлен в $n). Этот код заимствован у Prime Factors Buddies. Если вход $aуже прост, он вернется просто $a(важно позже). Это (потенциально просто $a) сохраняется в $d.

Следующее является if/ elseусловным. Для ifчасти мы проверяем, $nесть ли -in $d. Если это так, это означает, что $nэто простое число, поэтому мы берем $n=2*$n-1или $n+=$n-1. В противном случае он сложный, поэтому нам нужно найти самый большой простой фактор. Это означает , что нам нужно взять последний [-1]из $dи вычитать , что из $nс $n-=. Это работает, потому что мы зацикливаемся на 2и, следовательно, последний элемент $dуже будет самым большим.

Как только мы закончим цикл, мы просто помещаем $n%38(опять же, спасибо Арно) в конвейер, и вывод неявен.


1

APL (Dyalog Unicode) , 113 90 59 байт

CY 'dfns'
g←{1pco ⍵:f(2×⍵)-1f⍵-⊃⌽3pco ⍵}
f←{⍵∊3 19:⍵⋄g ⍵}

Попробуйте онлайн!

TIO работает со значениями до ~ 3200. Проверено на моем ПК для последнего теста. Чтобы проверить на TIO, просто добавьте f valueв конец кода. Больше не применяется, спасибо @ Adám за то, что он указал, что мой алгоритм проверки простоты был действительно плохим, и предоставил мне замену; также для 23-байтового сохранения.

Отредактировано, чтобы исправить количество байтов.

Как это работает

CY 'dfns'                      # Imports every Defined Function, which is shorter than importing just the function I used (pco).

g←{1pco ⍵:f(2×⍵)-1f⍵-⊃⌽3pco ⍵} 
g                              # define g as
   1pco ⍵:                      # if the argument ⍵ is prime
          f(2×⍵)-1              # Call f over 2×⍵-1
                  f            # else, call f over
                               # the first element of the
                      3pco     # list of prime factors of ⍵
                               # reversed

f←{⍵∊3 19:⍵⋄g ⍵}
f                              # Define f as
        :                      # if the argument ⍵
                               # is in
     3 19                       # the list [3, 19]
                               # return the argument ⍵
                               # else
            g                  # call g over the argument ⍵

1

Аксиома, 93 байта

h(n)==(repeat(n=3 or n=19 or n<2=>break;prime? n=>(n:=2*n-1);n:=n-last(factors(n)).factor);n)

тест:

(4) -> [[i,h(i)] for i in [10,74,94,417,991,9983]]
   (4)  [[10,3],[74,19],[94,3],[417,3],[991,19],[9983,19]]
                                                  Type: List List Integer

Там будет 68 байт функция

q x==(n<4=>3;n=19=>n;prime? n=>q(2*n-1);q(n-last(factors n).factor))

но для n = 57991 (если я хорошо помню) он выходит из зарезервированного стекового пространства.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.