Функція Мебіуса


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 значень μ:

Зображення публічного домену з Вікіпедії

Функція Мебіуса є порядковим номером 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==10

Завдяки Деннісу за збереження 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(не впевнений, чи був тоді вбудований, але зараз має бути добре).
Ерік Аутгольфер

10

Математика, 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квадратний вільний, то масив - це всі 1s, які стають усі -1s після поділу. Інакше, якщо 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

Ruby, 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::moebius16 байт.
Олексій А.

3

Піт , 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 Спасибі, я відредагував пост :)
Аднан

@ThomasKwa Ааа, я знайшов це. Це кодування CP-1252 .
Аднан

2

Піта, 11

*{IPQ^_1lPQ

Тестовий набір

Це помножує булеве значення, якщо прості коефіцієнти є квадратними, -1на потужність числа простих факторів, що має число.

Iце перевірка інваріантності попереднього оператора, який тут є {, який є єдиним оператором ify.



2

Юлія, 66 байт

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

Це лямбда-функція, яка приймає ціле число і повертає ціле число. Щоб викликати його, призначте його змінній.

Безголівки:

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 (завдяки Kevin Cruijssen )
-7 байт: змінено, якщо заява для циклу на термінал (спасибі Пітеру Тейлору та Кевіну Круйссену )

Безголівки:

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;.
Kevin Cruijssen

Так, все, що ви запропонували, виглядало правильно. Я коли-небудь так злегка хвилювався, коли ти сказав, що це неправильно, бо це означало б, що мій оригінальний код теж був неправильним! :)
Meerkat

1
Так, вибачте з цього приводу. :) Ще 1 байт у гольф btw - 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

GNU sed, 89 байт

#!/bin/sed -rf
s/.*/factor &/e
s/.*://
/\b([0-9]+) \1\b/!{
s/[0-9]+//g
s/$/1/
s/  //g
y/ /-/
}
s/ .*/0/


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, яку потрібно ввести в комірки від А1 до АХ50.



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 Мабуть, відповідь працює так само добре в Серйозно, і я не знаю, коли насправді вперше з’явився в Інтернеті, тому я перейшов на Серйозно, щоб бути в безпеці.
Шерлок9

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 .

Порт @ .NET C # відповідь Meerkat в , який я перший 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

Дивіться мій коментар до відповіді Меерката.
Пітер Тейлор

@PeterTaylor Smart, дякую! І тоді ще 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.