Функция Мёбиуса


23

Функция Мёбиуса

Функция Мёбиуса является важной теоретико-числовой функцией.

Ваша заявка должна принимать положительное целое число nи возвращать значение функции Мёбиуса, оцененной в n.

Определение

Функция Мёбиуса μ (n) определяется следующим образом:

       |  1 if n is squarefree and has an even number of distinct prime factors
μ(n) = | -1 if n is squarefree and has an odd number of distinct prime factors
       |  0 otherwise

nназывается квадратичным, если все показатели простой факторизации n строго меньше двух. (В качестве альтернативы: нет простого к силе двух делений n).

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

Здесь вы можете увидеть первые 50 значений μ:

Public Domain Image из Википедии

Функция Мёбиуса - это порядковый номер A008683 в OEIS.

Это первые 77 значений:

1, -1, -1, 0, -1, 1, -1, 0, 0, 1, -1, 0, -1, 1, 1, 0, -1, 0, -1, 0, 1, 1, -1, 0, 0, 1, 0, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 0, -1, -1, -1, 0, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, 1, 0, 1, 1, -1, 0, -1, 1, 0, 0, 1, -1, -1, 0, 1, -1, -1, 0, -1, 1, 0, 0, 1

Большие значения также могут быть легко проверены на Wolframalpha.com или в b-файле OEIS , как предложено @ MartinBüttner.

Ответы:


15

Python 2, 48 байт

m=lambda n,d=1:d%n and-m(d,n%d<1)+m(n,d+1)or 1/n

Более ранняя 51-байтовая версия:

m=lambda n:1/n-sum(m(k)for k in range(1,n)if n%k<1)

Мёбиус-инвертирует последовательность 1,0,0,0,0....

Функция Мёбиуса обладает свойством , что для любого n>1, функции Мёбиуса nсуммы делителей «S в 0. Таким образом, для n>1, μ(n)вычисляется отрицая сумма μ(k)всех делителей kиз n. Для n=1выхода есть 1.

Код обрабатывает базовый случай, добавляя деление на этаж 1/n, что дает 1для n==1и в 0противном случае.

Спасибо Деннису за сохранение 3 байта с лучшей рекурсивной обработкой, вдохновленной подобной структурой в этом вызове .


13

Желе , 7 байт

Код:

ÆF>1’PS

Объяснение:

ÆF       # This computes the prime factorization as well as the exponent
  >1     # Compares each element if it's greater than 1, resulting in 1's and 0's
    ’    # Decrement on each element
     P   # Compute the product
      S  # Compute the sum of the list

Например, число 10 :

ÆF       # [[2, 1], [5, 1]]
  >1     # [[1, 0], [1, 0]]
    ’    # [[0, -1], [0, -1]]
     P   # [0, 1]
      S  # 1

И результаты в 1 .

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


-1 байт: ÆFỊNPS(не уверен, был ли он тогда встроенным, но теперь все должно быть в порядке).
Эрик Outgolfer

10

Mathematica, 9 байт

MoebiusMu

Конечно, Mathematica имеет встроенный. (И , вероятно, все равно будет побит Джелли.)


7

CJam, 18 15 байтов

WrimFz~\1&+f/:*

Тот факт, что CJam возвращает 1 в встроенных факторизационных элементах, усложняет задачу n = 1.

Попробуй это онлайн | Тестирование

Спасибо @PeterTaylor за изящный 1&+прием для обработки 1 случая.

объяснение

W                 Push -1
 ri               Push input as int
   mF             Factorise input into [base exponent] pairs
     z~           Zip and unwrap pairs, leaving stack like [-1 bases exponents]
       \1&        Setwise intersect bases with 1, giving [1] for 1 and [] otherwise
          +       Append to exponent array
           f/     Divide the previously pushed -1 by each element in the array 
                  This gives -1 for 1s and 0 otherwise, since / is int division
             :*   Take product

Ибо n > 1измененный массив - это просто массив экспонент. Если значение nравно четырем, то массив равен всем 1 с, которые становятся равными -1 с после деления. В противном случае, если n имеет делитель простого квадрата, то где-то после деления будет 0, что дает произведение 0.

Для n = 1модифицированного массива есть [1] + [1], который делается [-1 -1]после деления, давая произведение 1.


Альтернатива 16:

rimF{1#2+3%(}%:*

Это использует #(найти) в каждом [base exponent]массиве, чтобы найти 1, а затем карты -1 -> 0, 0 -> 1, 1 -> -1.


6

Рубин, 65 + 7 = 72 62 + 7 = 69 байт

->x{((d=x.prime_division).all?{|_,n|n<2}?1:0)*(d.size%2*-2+1)}

+7 байт за -rprimeфлаг.

Мы делаем это очень наивно:

->x{
 (
  (d=x.prime_division)  # ex. input 20 results in [[2,2],[5,1]] here
  .all?{|_,n|n<2}?      # are all factors' exponents under 2?
  1:0                   # if so, result in a 1; otherwise, a 0
 )
 *                      # multiply that 1 or 0 by...
  (d.size%2*-2+1)       # magic
}

«Волшебная» часть дает 1, если число четное, и -1 в противном случае. Вот как:

Expression       Even  Odd
--------------------------
d.size%2         0     1
d.size%2*-2      0     -2
d.size%2*-2+1    1     -1

5

Pyth, 9 байт

^_{IPQlPQ

Объяснение:

^_{IPQlPQ    Implicit: Q=input
    PQ       Prime factorization of Q
  {I         Is invariant under uniquify.
  {IPQ       1 if Q is squarefree; 0 otherwise.
 _{IPQ       -1 if Q is squarefree; 0 otherwise.
^     lPQ    Exponentiation to length of PQ.

Попытайся здесь .


5

Лабиринт , 87 байт

1
:
}
?   @ "}){/{=:
""({! "      ;
} )   :}}:={%"
* _}}){     ;
{      #}):{{
")`%#/{+

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

Краткое объяснение

Вот порт используемого алгоритма в Python:

divisor = 1
mobius = 1
n = int(input())

while n != 1:
  divisor += 1
  count = 0

  while n % divisor == 0:
    n //= divisor
    count += 1

  mobius *= (count + 3)//(count + 1)%3*-1 + 1

print(mobius)

Длинное объяснение

Обычный праймер по лабиринту:

  • Лабиринт является основанным на стеке и двумерным, выполнение начинается с первого распознанного символа. Существует два стека: основной стек и вспомогательный стек, но большинство операторов работают только с основным стеком.
  • В каждой ветви лабиринта проверяется вершина стека, чтобы определить, куда идти дальше. Отрицательный - поворот налево, ноль - прямой, а положительный поворот направо.

Выполнение этой программы начинается слева вверху 1.

Outer preparation
=================

1        Pop 0 (stack is bottomless and filled with 0s) and push 0*10+1 = 1
:}       Duplicate and shift to auxiliary stack
?        Read int from input
         Stack is now [div=1 n | mob=1]

Top of stack positive but can't turn right. Turn left into outer loop.

Begin outer loop
================
Inner preparation
-----------------

(        Decrement top of stack

If top was 1 (and is now zero), move forward and do...
------------------------------------------------------

{!       Print mob
@        Terminate

If top of stack was greater than 1, turn right and do...
--------------------------------------------------------

)        Increment n back to its previous value
_}       Push 0 and shift to aux
         This will count the number of times n can be divided by div
}){      Increment div
         Stack is now [div n | count mob]

Inner loop
----------

:}}      Dup n, shift both n's to aux
:=       Dup div and swap top of main with top of aux
{%       Shift div down and take mod
         Stack is now [div n%div | n count mob]

If n%div == 0, move forward and do...
-----------------------------------

;        Pop n%div
:={/     Turn n into n/div
{)}      Increment count
         (continue inner loop)

If n%div != 0, turn right (breaking out of inner loop) and do...
================================================================

;        Pop n%div
{{       Pull n and count from aux
:)}      Dup and increment count, giving (count+1), and shift to aux
#+       Add length of stack to count, giving (count+3)
{/       Calculate (count+3)/(count+1)
#%       Mod by length of stack, giving (count+3)/(count+1)%3
`        Multiply by -1
)        Increment, giving (count+3)/(count+1)%3*-1 + 1
         This is 1 if count was 0, -1 if count was 1 and 0 if count > 1
{*}      Multiply mob by this number
         (continue outer loop)


4

R 39 16 байт

numbers::moebius

Требуется, чтобы в вашей системе был установлен пакет с номерами ...

Редактировать: гораздо проще, если я правильно прочитал спецификации [спасибо @AlexA.]


Это возвращает функцию Мёбиуса, вычисленную для каждого целого числа от 1 до входа, но задача для этой задачи - просто оценить функцию Мёбиуса на входе.
Алекс А.

В соответствии с ответом Mathematica, вы могли бы даже сделать просто numbers::moebiusдля 16 байтов.
Алекс А.

3

Pyth , 16 байт

?nl{PQlPQZ^_1lPQ

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

Мой первый актуальный ответ Pyth. Предложения приветствуются! :)

объяснение

Мое решение использует тот факт, что число не содержит квадратов, если его простые множители не содержат числа более одного раза. Если входное значение не содержит квадратов, функция Мёбиуса принимает значение -1 ^ (число простых множителей).


?n        if not equal
  l{PQ      length of the list of the distinct input-Primefactors
  lPQ       length of the list of primefactors including duplicates    
    Z         Input is not squarefree, so output Zero
  ^_1lPQ  if input is squarefree, output -1^(number of prime-factors)

3

MATL , 15 17 байт

tq?YftdAwn-1w^*

Используется текущий выпуск (10.1.0) языка / компилятора.

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

объяснение

t         % implicit input. Duplicate that
q         % decrement by 1. Gives truthy (nonzero) if input exceeds 1
?         % if input exceeds 1, compute function. Otherwise leave 1 on the stack
  Yf      % vector of prime factors. Results are sorted and possibly repeated
  td      % duplicate and compute differences
  A       % true if all differences are nonzero
  w       % swap
  n       % number of elements in vector of prime factors, "x"
  -1w^    % -1^x: gives -1 if x odd, 1 if x even 
  *       % multiply by previously obtained true/false value, so non-square-free gives 0
          % implicitly end "if"
          % implicitly display stack contents

3

05AB1E , 8 байтов, неконкурентный

Черт возьми, еще раз ошибка, которая делает мое представление неконкурентоспособным. Код:

.p0K1›<P

Объяснение:

.p        # Get the prime factorization exponents
  0K      # Remove all zeroes from the list
    1›    # Compare each element if greater than 1
      <   # Decrement on each element
       P  # Take the product

Использует кодировку CP-1252


отсутствует в ISO 8859-1 ...
ETHproductions

1
@ETHproductions Хех? Что это за кодировка? Я получил это с этого сайта .
Аднан

Я считаю, что это называется Extended ASCII .
ETHproductions

@ETHproductions Спасибо, я отредактировал сообщение :)
Adnan

@ThomasKwa Ааа, я нашел это. Это кодировка CP-1252 .
Аднан

2

Пиф, 11

*{IPQ^_1lPQ

Тестирование

Это умножает логическое значение, если простые множители являются квадратными -1 на степень числа простых факторов, которое имеет число.

Iпроверка инвариантности предыдущего оператора, который здесь есть {, который является оператором unique-ify.



2

Юлия, 66 байт

n->(f=factor(n);any([values(f)...].>1)?0:length(keys(f))%2>0?-1:1)

Это лямбда-функция, которая принимает целое число и возвращает целое число. Чтобы вызвать его, присвойте его переменной.

Ungolfed:

function µ(n::Int)
    # Get the prime factorization of n as a Dict with keys as primes
    # and values as exponents
    f = factor(n)

    # Return 0 for non-squarefree, otherwise check the length of the list
    # of primes
    any([values(f)...] .> 1) ? 0 : length(keys(f)) % 2 > 0 ? -1 : 1
end


2

Серьезно, 19 18 байт

,w;`iX1=`Mπ)l1&τD*

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

Объяснение:

,w;`iXDY`Mπ)l1&τD*
,w;                push two copies of the full prime factorization of the input
                      (a list of [base, exponent] pairs)
   `    `M         map the following function:
    iX1=             flatten list, discard, equal to 1
                        (push 1 if exponent == 1 else 0)
          π)       product of list, push to bottom of stack
            1&     push 1 if the # of prime factors is even else 0
              τD   double and decrement (transform [0,1] to [-1,1])
                *  multiply

2

C # (.NET Core) , 86 73 72 65 байт

a=>{int b=1,i=1;for(;++i<=a;)b=a%i<1?(a/=i)%i<1?0:-b:b;return b;}

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

-13 байт: упорядоченные циклы, добавлена ​​возвращаемая переменная (благодаря Кевину Круйссену )
-1 байт: изменен параметр b на ноль на троичный с if (благодаря Кевину Круйссену )
-7 байт: изменен оператор if в цикле for на троичный (спасибо Питеру Тейлору и Кевину Круйссену )

Ungolfed:

a => {
    int b = 1, i = 1;           // initialize b and i to 1

    for(; ++i <= a;)            // loop from 2 (first prime) to a
        b = a % i < 1 ?                     // ternary: if a is divisible by i
            ((a /= i) % i < 1 ? 0 : -b) :   // if true: set b to 0 if a is divisible by i squared, otherwise flip sign of b
            b;                              // if false: don't change b

    return b;                   // return b (positive for even numbers of primes, negative for odd, zero for squares)
}

1
73 байта я изменил int b=1;for(int i=1;на int b=1,i=1;for(;. Убраны {}скобки для цикла. Поменял оба a%i==0на a%i<1. Изменено b*=-1;на b=-b;. И , наконец , изменилась return 0;к b=0;.
Кевин Круйссен

Да, все, что ты предложил, выглядело правильно. Я был немного обеспокоен, когда ты сказал, что это неправильно, потому что это означало бы, что мой оригинальный код тоже был неправильным! :)
Сурикат

1
Да, извините за это. :) более 1 байт для гольфа кстати является if(a%i<1)b=0;в b=a%i<1?0:b;.
Кевин Круйссен

2
На самом деле, это упускает из виду легкое улучшение: b=-b;b=a%i<1?0:b;гольфb=a%i<1?0:-b;
Питер Тейлор

1
Продолжая @ гольф PeterTaylor в выше, вы можете изменить , if(a%i<1){a/=i;b=a%i<1?0:-b;}чтобы b=a%i<1?(a/=i)%i<1?0:-b:b;спасти больше 3 байта.
Кевин Круйссен



1

Microsoft Office Excel, британская версия, 196 байт

=IF(ROW()>=COLUMN(),IF(AND(ROW()=1,COLUMN()=1),1,IF(COLUMN()=1,
-SUM(INDIRECT(ADDRESS(ROW(),2)&":"&ADDRESS(ROW(),ROW()))),
IF(MOD(ROW(),COLUMN())=0,INDIRECT(ADDRESS(FLOOR(ROW()/COLUMN(),1),
1)),""))),"")

Формула ячейки Excel должна быть введена в ячейки с A1 по AX50.



1

Серьезно, 11 байтов

Предложения по игре в гольф приветствуются. Попробуйте онлайн!

;y;l0~ⁿ)π=*

Ungolfing

     Implicit input n.
;    Duplicate n.
y    Push a list of the distinct prime factors of n. Call it dpf.
;    Duplicate dpf.
l    Push len(dpf).
0~   Push -1.
ⁿ    Push (-1)**len(dpf).
)    Rotate (-1)**len(dpf) to BOS. Stack: dpf, n, (-1)**len(dpf)
π    Push product(dpf).
=    Check if product(dpf) == n.
      This is only true if n is squarefree.
*    Multiply (n is squarefree) by (-1)**len(dpf).
     Implicit return.

Хорошее решение =) (Я полагаю, однако, что этот язык моложе вопроса, не так ли?)
flawr

@flawr Очевидно, что ответ на Seriously работает так же хорошо, и я не знаю, когда на самом деле впервые появился в сети, поэтому я перешел на Seriously, чтобы быть в безопасности.
Sherlock9

1

Java 8, 72 68 65 байт

n->{int r=1,i=1;for(;++i<=n;)r=n%i<1?(n/=i)%i<1?0:-r:r;return r;}

-4 байта благодаря @PeterTaylor .

Порт ответа @ Meerkat на .NET C # , который я первый golfed немного дальше, поэтому убедитесь , что upvote его!

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

Объяснение:

n->{                 // Method with integer as both parameter and return-type
  int r=1,           //  Result-integer, starting at 1
  i=1;for(;++i<=n;)  //  Loop `i` in the range [1, n]:
    r=n%i<1?         //   If `n` is divisible by `i`:
       (n/=i)        //    Divide `n` by `i` first
        %i<1?        //    And if `n` is still divisible by `i`:
         0           //     Change `r` to 0
        :            //    Else:
         -r          //     Swap the sign of `r` (positive to negative or vice-versa)
      :              //    Else:
       r;            //     Leave `r` unchanged
  return r;}         //  Return `r` as result

Смотрите мой комментарий к ответу Meerkat.
Питер Тейлор

@PeterTaylor Смарт, спасибо! И тогда еще 3 байта могут быть сохранены с помощью r=n%i<1?(n/=i)%i<1?0:-r:r;.
Кевин Круйссен

0

Javascript (ES6), 48 байт

f=(n,i=1)=>n-1?n%++i?f(n,i):(n/=i)%i?-f(n,i):0:1

Прежде всего - это мой первый пост по гольфу, поэтому я могу до некоторой степени неправильно понять правила. В этом представлении последний персонаж; может быть опущен, и он все равно будет работать, но я даже не уверен, будет ли код действительным в соответствии со спецификациями ES6. В любом случае, краткое объяснение.

Сначала я немного объясню идею; мы берем n, и мы пытаемся разделить его на целое число i. Если он делится, то мы делаем это и проверяем, делим ли он iснова. Если это так, то нам нужно вернуться 0. В противном случае мы можем попробовать другое i. Круто то, что мы можем просто начать i=2и просто увеличивать его с 1каждым разом, чтобы разделить все основные факторы.

Итак, код работает так:

f=(n,i=1)=>                                           We will increase i by one at the start of
                                                         the function body, so default is 1
           n-1?                                       Check if n==1.
               n%++i?                                 If i isn't, increase i by 1, check if n
                                                         is divisible by i
                     f(n,i):                          if it isn't, we check the next i
                            (n/=i)%i?                 if it is, divide n by i, and check for
                                                         divisibility by i again
                                     -f(n,i):         if it not, then we flip the value to
                                                         account for the 1 and -1 depending on the
                                                         amount of factors
                                             0:       if it's divisible by i twice, done.
                                               1      if we're at 1, divided out all factors,
                                                         then we return 1. The line with
                                                         -f(n,i) will then take care of the sign

Итак, это мое представление.


Добро пожаловать на сайт. Я не знаю JS, но я могу сказать вам, что здесь мы не заботимся о спецификациях, только реализации. Так что, если удаление ;не сломает, не имеет значения, какие спецификации вы можете удалить.
Пшеничный волшебник

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