Знайдіть суму дільників N


20

Напишіть програму, яка відобразить на екрані суму дільників числа (1 ≤ N ≤ 100), введених користувачем у діапазоні від 1 до N.

Це OEIS A000203 .


Приклади:

Вхід : 7

7 / 1 = 7
7 / 7 = 1

7 + 1 = 8

Вихід: 8


Вхід: 15

15 / 1 = 15
15 / 3 = 5
15 / 5 = 3
15 / 15 = 1

15 + 5 + 3 + 1 = 24

Вихід: 24


Вхід: 20

20 / 1 = 20
20 / 2 = 10
20 / 4 = 5
20 / 5 = 4
20 / 10 = 2
20 / 20 = 1

20 + 10 + 5 + 4 + 2 + 1 = 42

Вихід: 42


Вхід: 1

1 / 1 = 1

Вихід: 1


Вхід: 5

5 / 1 = 5
5 / 5 = 1

5 + 1 = 6

Вихід: 6


6
@ H.PWiz Я думаю, що він означає "дільники числа N"
бензол

Я думаю, ви маєте на увазі суму дільників, також функцію сигми ?
Стівен

Вибачте, я маю на увазі "Сума кратної N".
Кевін Галлей

@ H.PWiz це сума цих, тому я не знаю
Стівен

@Stephen Це здається мені тривіальною зміною
H.PWiz

Відповіді:



6

x86-64 Машинний код, 23 байти

89 F9 89 FE EB 0D 89 F8 99 F7 F1 85 D2 99 0F 44 D1 01 D6 E2 F1 96 C3

Вищеописані байти коду визначають функцію, яка приймає єдине ціле число, N і повертає в результаті суму його кратних.

Єдиний параметр передається в EDIреєстр, що відповідає системі V V AMD64 ABI (як це використовується в системах * nix). Результат повертається в EAXреєстр, як і у всіх конвенціях викликів x86.

Алгоритм дуже простий, подібний до багатьох інших матеріалів інших мов. Ми крутимо N разів, кожен раз обчислюючи модуль і додаючи це до нашої загальної кількості.

Невикольована збірна мнемоніка:

; unsigned SumOfMultiples(unsigned N  /* (EDI) */)
    mov     ecx, edi      ; make copy of input N, to be used as our loop counter
    mov     esi, edi      ; make copy of input N, to be used as our accumulator
    jmp     CheckEnd      ; jump directly to 'CheckEnd'
AddModulo:
    mov     eax, edi      ; make copy of input N, to be used as input to DIV instruction
    cdq                   ; short way of setting EDX to 0, based on EAX
    div     ecx           ; divide EDX:EAX by ECX, placing remainder in EDX
    test    edx, edx      ; test remainder, and set ZF if it is zero
    cdq                   ; again, set EDX to 0, without clobbering flags
    cmovz   edx, ecx      ; set EDX to ECX only if remainder was zero (EDX = ZF ? 0 : ECX)
    add     esi, edx      ; add EDX to accumulator
CheckEnd:
    loop    AddModulo     ; decrement loop counter (ECX), and keep looping if it != 0
    xchg    eax, esi      ; move result from accumulator (ESI) into EAX
    ret                   ; return, with result in EAX

Спробуйте в Інтернеті!

Звичайно, схоже, що має бути спосіб скоротити це, але я не можу його бачити. Обчислювальний модуль на x86 займає зовсім небагато коду, оскільки ви робите це за допомогою DIV(або IDIV) інструкції, і обидва користуються фіксованими вхідними регістрами ( EDXі EAX), значення яких стають клобованими (оскільки вони отримують результати, решту та коефіцієнт відповідно).

Єдині справжні хитрощі - це досить стандартні ігри для гольфу:

  • Я структурував код дещо незвично, щоб я міг використовувати LOOPінструкцію в стилі CISC , яка в основному є лише комбінацією DEC+ JNZз ECXрегістром як неявний операнд.
  • Я використовую XCHGв кінці замість того, MOVщо перший має спеціальне 1-байтове кодування, коли EAXє одним із операндів.
  • Я використовую CDQдля нульового відключення EDXпід час підготовки до поділу, навіть якщо для безпідписаного поділу ви зазвичай просто нульові, використовуючи a XOR. Однак XORзавжди є 2 байти, тоді CDQяк лише 1 байт. Я CDQзнову використовую вдруге всередині циклу до нуля EDX, перед CMOVZінструкцією. Це працює, тому що я можу гарантувати, що коефіцієнт ділення (в EAX) завжди не підписаний, тому розширення знака на EDXбуде встановлено EDXрівним 0.




3

Математика, 14 байт

Tr@Divisors@#&   

або відповідь @Loki

Математика, 17 байт

DivisorSum[#,#&]&

@Jennymathy Дуже приємно, дякую! Еквівалентний і смішний спосіб його написати також: DivisorSum [#, # &] &
Rebel-Scum

@Jennymathy Хм, це ще краще: Total @ Divisors @ лише 15 символів! І це працює: наприклад, Total @ Divisors @ 15 дає 24, як очікувалося. Mathematica FTW :)
Rebel-Scum

2
@Loki та Tr@Divisors@#&ще краще ;-)
J42161217

1
@Loki програма повинна бути функцією, f=яка приймає вхід f [x], тому я представляю її таким чином. Вітаю в PPCG
J42161217

3
Ви можете Tr@*Divisorsголити байт.
wchargin

3

C, C ++, C #, D, Java, 65 62 байти

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

Це працює у всіх тезах 5 мов програмування через подібність.

Оптимізація C, C ++ та D: 62 60 байт

У C ++ і D цілі числа неявно перетворюються на булеві (Zero => false, Not Zero => true), тому вам не потрібно мати !=0

int d(int n){int s=0,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}

Оптимізація D: система шаблонів golfy, 55 байт

T d(T)(T n){T s,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}

Код для тестування :

C:

printf("%d %d %d %d %d", d(7), d(15), d(20), d(1), d(5));

C ++:

std::cout << d(7) << ' ' << d(15) << ' ' << d(20) << ' ' << d(1) << ' ' << d(5);

C #:

class FindSum
{
    int d(int n) { int s = 0, i = 1; for (; i <= n; ++i) s += n % i > 0 ? 0 : i; return s; }

    static void Main(string[] args)
    {
        var f = new FindSum();
        Console.WriteLine(string.Format("{0}, {1}, {2}, {3}, {4}", f.d(7), f.d(15), f.d(20), f.d(1), f.d(5)));
    }
}

D:

writeln(d(7));
writeln(d(15));
writeln(d(20));
writeln(d(1));
writeln(d(5));

Java:

public class FindSum {
    int d(int n){int s=0,i=1;for(;i<=n;++i)s+=n%i>0?0:i;return s;}

    public static void main(String[] args) {
        FindSum f = new FindSum();
        System.out.println(String.format("%d, %d, %d, %d, %d", f.d(7), f.d(15), f.d(20), f.d(1), f.d(5)));
    }
}

Кілька речей: По-перше, я не думаю, що вам потрібні дужки навколо n%i/ n%i!=0на будь-якій з мов. По-друге, ваше перше рішення має мати можливість мати n%i>0замість n%i!=0. По-третє, рішення D може бути T d(T)(T n){T s,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}шляхом зловживання шаблоною системи та значень за замовчуванням.
Zacharý

3

Шнап , 44 43 байт

-1 до побачення завдяки містеру Xcoder (хай я перевершив свою рідну мову)

 $n return:{s=0for d:range(n+1)if n%d<1s+=d}

Це функція ( $запускає функцію в Shnap).

Спробуйте в Інтернеті!

Пояснення:

$ n                        //Start function with parameter n
    return: {              //Technically, we are returning a scope-block, which evaluates to the last statement run
        s = 0              //Our result
        for d : range(n+1) //For each value in the iterator range(n+1)
            if n % d < 1  // If n is divisible by d
                s += d     // Add d to the sum
                           // Since (s += d) returns (s + d), and a scope-block returns the last run statement, this will be the last statement and equal to our result
    }

Без конкуренції, 19 байт

Після багатьох оновлень мови тепер це може бути зменшено до неміцних 19 байт:

$n=>sum(factors(n))

Спробуйте в Інтернеті!



@Містер. Xcoder спасибі ... Я був перевершений ... Моєю рідною мовою ... Що не є навіть езотеричним xD
Сократичний Фенікс

2

Пітон, 44 байти

lambda k:sum(i*(k%i<1)for i in range(1,1+k))
  • Завдяки Стівену, збережіть 1 байт, видаливши пробіл.
  • Завдяки Джонатану Фреху збережіть ще 1 байт, змінивши, чи потрібно помножувати.

2

J, 23 байти

[:+/](([:=&0]|[)#])1+i.

Спробуйте в Інтернеті!

Для шанувальників J існує a розумне 13-байтне рішення :>:@#.~/.~&.q: але оскільки це не було моїм винаходом, я не розміщую це як свою офіційну відповідь.

Моє власне рішення просто фільтрує 1..n, знаходячи дільники, потім підсумовує їх. Суть в ньому - діадична вилка

](([:=&0]|[)#])

Зауважимо, що в цьому контексті ]дорівнює 1..n, і [є n самим n. Отже ]|[, залишки під час ділення кожного елемента 1..n на n і =&0повідомляють, чи дорівнюють вони 0.


2
Це для 13 байтів має бути рівнозначним:+1#.i.*0=i.|]
миль

@miles, це дійсно приємно. Ця частина - i.|]це велике вдосконалення мого підходу. Я не повністю розумію цю частину, хоча: +1#.i.- ви могли б це пояснити?
Йона

2
1#.- це конверсія бази 1, що еквівалентно +/"1. Спочатку i.|]дістаньте залишки, потім 0=знайдіть ті, що дорівнюють 0 (дільникам), потім i.*нуль неділізорів у діапазоні, потім підсумовуйте 1#., а потім додайте +себе, оскільки i.це ексклюзивний діапазон.
миль




2

Javascript, 54 44 байт

n=>[...Array(x=n)].reduce(y=>y+!(n%x)*x--,0)

Збережено 10 байт завдяки Шаггі

Спробуйте в Інтернеті!

const f = n=>[...Array(x=n)].reduce(y=>y+!(n%x)*x--,0)

console.log(f(7))
console.log(f(15))
console.log(f(20))
console.log(f(1))
console.log(f(5))


2

Мозок-Флак , 96 байт

((({})<>){<(([()]{})){<>(({})(<()>))<>{(({})){({}[()])<>}{}}{}<>([{}()]({})){((<{}{}>))}}{}>{}})

Спробуйте в Інтернеті!

Пояснення:

Зараз застарілі покращення.

Основою алгоритму є:

({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]({})) turns |N, M...| into |N mod M, M...|
{((<{}{}>))} if the top of stack is not zero, replace it and the second with zero

Це модифікація моди, яка дасть нам, Mякщо вона є фактором Nта 0іншим чином. Повний код нижче.

((({})<>) place input, N on both stacks
{ Loop to find factors
 <
  (([()]{})) Decrement and Duplicate; get next factor to check
  { if not zero
   (<>({})<>) Copy N from other stack
   ({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]({})){((<{}{}>))} Code explained above
  }
  {} drop the zero
 >
 {} add the factor
}) push the sum

У вас є пояснення?
Пшеничний майстер

@FunkyComputerMan У мене зараз є!
MegaTom

2

R , 31 26 байт

function(N)(x=1:N)%*%!N%%x

Спробуйте в Інтернеті!

Повертає a 1x1 матрицю.

Обчислює !N%%xкарти елементів dз 1:Nпо:d->(1 if d divides N, 0 otherwise)

Тоді x%*%x!N%%xматриця продукт 1:N, результати якого в сумі , xде !N%%xзнаходиться 1. Акуратно! Технічно є портом Октава Луїса Мендо, але я це побачив лише після того, як я подумав про це.

R + числа, 14 байт

numbers::Sigma

Спробуйте в Інтернеті!


Для першого ви можете зберегти 2 байти за допомогоюN=scan();
gstats

@gstats так, але тоді я повинен отримати +4 байти за мета-дискусію . Якщо у вас є думка, ви можете зважитися на відповідь Ярка, але, як ніхто не запропонував альтернативи, це є в моїй думці.
Джузеппе

Чи не повинно бути другого numbers::Sigma(N)? У такий спосіб він виводить вихідний код функції Sigma.
Rui Barradas - Відновити Монік

@RuiBarradas функція - це ідеально хороша подача. щоб перевірити це, ви, очевидно, повинні називати це, як я роблю в першому поданні.
Джузеппе




1

VBA (Excel), 73 байти

a=Cells(1,1)
x=1
While x<=a
If a Mod x = 0 Then b=b+x
x=x+1
Wend
MsgBox b

Ця відповідь є недійсною, оскільки це колекція фрагментів, яку не можна запустити як єдину одиницю як стенд. Щоб зробити це дійсно, вам потрібно буде перетворити це на підпрограму або анонімну функцію негайного вікна VBE.
Тейлор Скотт

Я не дуже знайомий у тому, що ви сказали. Чи можете ви мені трохи більше допомогти?
remoel

Щоб зробити цю публікацію дійсною, вам доведеться перетворити її в один із наступних форматів: 1 - Підпрограма, 2 - Функція, 3 - Анонімна функція негайного вікна VBE (єдиний рядок, який може бути виконаний у негайному вікні); Для вашої реалізації найпростішою реалізацією цього способу було б перетворення на підпрограму, обернувшись Sub Y..., End Subщоб отримати 85-байтне рішенняSub y A=Cells(1,1) x=1 While x<=A If A Mod x=0 Then b=b+x x=x+1 Wend MsgBox b End Sub
Тейлор Скотт

Це, однак, може бути досить оптимізовано вниз до 72-байтового рішення, Sub y While x<=[A1] x=x+1 If [A1]Mod x=0Then b=b+x Wend Debug.?b End Subяке передбачає, що воно запускається в чистому модулі (x = значення int за замовчуванням, 0) і виводить у безпосереднє вікно VBE ( ?автоформати до Print )
Тейлор Скотт,

Крім цього, і визнаючи , що ваше рішення не приймає введення з допомогою виклику підпрограми, це може бути перетворено в VBE безпосередній функцію вікна для 50 байт , While x<=[A1]:x=x+1:b=IIf([A1]Mod x,b,b+x):Wend:?bякий передбачає , що x, bє значення за замовчуванням 0 і виводить найближчим вікно VBE (від Пряме вікно VBE ?еквівалентно Debug.Print )
Тейлор Скотт

1

Pyth , 6 байт

s*M{yP

Спробуйте тут!

Pyth не має вбудованого для дільників, тому я вважаю це розумним.

Пояснення

s * M {yP - Повна програма з неявним введенням.

     P - Прості коефіцієнти вхідних даних.
    y - Набір потужностей його основних факторів.
   {- Дублікат.
 * M - Карта з множенням.
s - сума.
          - Неявно відображати результат.

20Наприклад, враховуючи , що це робить наша програма після кожної інструкції:

  • P: [2, 2, 5].

  • y: [[], [2], [2], [5], [2, 2], [2, 5], [2, 5], [2, 2, 5]].

  • {: [[], [2], [5], [2, 2], [2, 5], [2, 2, 5]].

  • *M: [1, 2, 5, 4, 10, 20].

  • s: 42.







0

Bash + GNU utilities, 36

bc<<<`seq -f"n=%g;a+=n*!$1%%n;" $1`a

Try it online.


Pure Bash, 41

for((;++i<=$1;a+=$1%i?0:i))
{
:
}
echo $a

Try it online.

I first tried a fancy bash expansion answer, but it ended up being longer than the simple loop above:

echo $[$(eval echo +\\\(n={1..$1},$1%n?0:n\\\))]


0

QBIC, 17 bytes

[:|~b%a|\p=p+a}?p

Explanation

[:|      FOR a = 1; a <= b (read from cmd line); a++
~b%a|    IF b modulo a has a remainder THEN - empty block - 
\p=p+a   ELSE add divisor 'a' to running total 'p'
}        END IF, NEXT
?p       PRINT p

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.