Сложный процент… с деньгами волшебника


15

Гринготтс - это не просто хранилище, но заслуживающее доверия финансовое учреждение и волшебники тоже нуждаются в кредитах. Поскольку вы не хотите, чтобы гоблины Гринготта облажались, вы решили, что было бы неплохо написать программу для начисления процентов. Интерес накапливается только ежегодно.

Ваша задача состоит в том, чтобы рассчитать общую сумму задолженности после начисления процентов с учетом основной суммы, процентной ставки и времени (целых лет), действуя в целых деноминациях волшебных денег, с округлением до ближайшего целого Кнута. Есть 29 Бронзовых Кнутов в Серебряном Серпе и 17 Серпов в Золотом Галеоне.

пример

Loan taken out:
 23 Knuts
 16 Sickles
103 Galleons
@ 7.250%
For 3 years

Total owed after interest:
 24 Knuts
  4 Sickles
128 Galleons

Примечания и правила

  • Вход и выход могут быть в любом удобном формате. Вы должны взять Кнуты, Серпы, Галеоны, процентную ставку и время. Все, кроме процентной ставки, будут целыми числами. Процентная ставка составляет 0,125%.
  • Ввод денег не гарантированно будет каноническим (то есть вы можете иметь 29 или более Кнутов и 17 или более Серпов).
  • Вывод должен быть каноническим представлением. (т.е. менее 29 кнутов и менее 17 серпов)
  • Общая сумма долга до 1000 галеонов должна быть точной с точностью до 1 кнута в год для интереса по сравнению с вычислениями произвольной точности.
    • Вы можете округлять после каждого интересующего года или только в конце. Эталонные расчеты могут учитывать это при проверках точности.

Удачного игры в гольф!


4
Можем ли мы принять процентную ставку в виде десятичной дроби вместо процента? (например, 0.0725вместо 7.25)
Shaggy

@ Shaggy Я также хотел бы знать это
senox13

Если ссуда составляет ровно 1 кнут, процент составляет 99% в год, а срок составляет 1 год, должен ли результат быть «1 кнут» или «2 кнута»?
Час Браун

Другими словами, просьба уточнить математическое значение фразыrounding down
senox13

1
@ChasBrown: 1 Кнут. Функция усечения / пола до ближайшего целого кнута.
Beefster

Ответы:


6

R , 70 62 байта

function(d,i,y)(x=d%*%(a=c(1,29,493))*(1+i)^y)%/%a%%c(29,17,x)

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

Принимает входные данные в виде d: депозит в кнутах, серпах, галеонах; я: процентная ставка в десятичном виде; у: лет. Выводит итоговый депозит в кнутах, серпах, галеонах. Спасибо @Giuseppe за использование умножения матриц для сохранения некоторых байтов (и указание, как избежать необходимости переноса в 1e99).


Я не знаю R; что заставляет их оборачиваться?
dfeuer

@dfeuer, они взяли мод 1e99, поэтому, если ваши галеоны поднимутся так высоко, они упадут до нуля
Ник Кеннеди

Что мне интересно, так это то, что вы получаете, взяв их мод 1e99.
dfeuer

Большинство функций R векторизованы. В этом случае я передаю вывод через %%функцию, которая является модом. В идеале, я бы хотел оставить галеоны в покое, но, взяв бесконечность числового мода, возвращает NaN, и поэтому я просто использовал действительно большое число (но то, которое мало в байтах). Альтернативы, которые я придумал, длиннее (например, [ tio.run/##JYrLCsIwEEV/… попробуйте онлайн!])
Ник Кеннеди

@NickKennedy, вы могли бы сделать 9e99так же ... Кроме того, вы можете
Джузеппе

4

Python 3.8 (предварительная версия) , 75 74 71 байт

-1 байт благодаря @EmbodimentofIgnorance
-3 байт благодаря @xnor

Это принимает Кнуты, Серпы и Галеоны как целые числа, проценты как число с плавающей запятой (десятичное число, а не процент), а годы как целое число. Возвращает кортеж, содержащий число после интереса Knuts, Sickles и Galleons соответственно.

lambda K,S,G,R,Y:((k:=int((K+G*493+S*29)*(1+R)**Y))%29,k//29%17,k//493)

Использование:

>>> print(I(23,16,103,0.0725,3))
(24, 4, 128)

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


Хороший улов. Обновление ответа
senox13

Вопрос говорит operating in whole denominations of wizard money, rounding down. Я имел rounding downв виду chop off everything after the decimal point.Использование заголовка определенно звучит как более простой способ сделать вещи. Я сделаю это для будущих сообщений, спасибо
senox13

Это звучит скорее как «усечение», чем «округление»; но я попросил у ОП уточнения (потому что здесь, в PPCG, название игры - «азартная добыча» :)).
Час Браун

Я не согласен с вами, это то значение, которое я всегда видел для округления, потому что вы всегда округляете до целого числа ниже своего результата. В противном случае это просто нормальное округление. Позвольте ОП решить, что это хорошая идея
senox13

К вашему сведению, полезный трюк, позволяющий сделать анонимные функции тестируемыми на TIO, заключается в том, чтобы поместить их I\=в заголовок следующим образом . Кроме того, похоже, k//29//17может бытьk//493 .
xnor

3

APL + WIN, 37 28 26 байт

⌊a⊤((a←0 17 29)⊥⎕)×(1+⎕)*⎕

2 байта сохранены благодаря lirtosiast

Попробуйте онлайн! Предоставлено Dyalog Classic

Объяснение:

(1+⎕)*⎕ prompts for years followed by decimal interest rate and calculates
         compounding multiplier

((a←0 17 29)⊥⎕) prompts for Galleons, Sickles and Knuts and converts to Knuts

⌊a⊤ converts back to Galleons, Sickles and Knuts and floor 
    after applying compound interest. 

⌊a⊤(⎕⊥⍨a←0 17 29)×⎕*⍨1+⎕за 24?
lirtosiast

@lirtosiast Спасибо, но я боюсь, что мой древний интерпретатор APL + WIN не имеет функции ⍨. Обязательно отправьте это как собственное решение APL.
Грэм

@lirtosiast Еще раз спасибо, я взял 2 байта, полученных в результате присвоения a.
Грэм

3

Perl 6 , 47 байт

((1+*)*** *(*Z*1,29,493).sum+|0).polymod(29,17)

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

Я удивлен, что мне удалось превратить это в анонимную Лямбду! Особенно часть, где это больше* чем что-либо еще. Принимает ввод как interest rate (e.g. 0.0725), years, [Knuts, Sickles, Galleons]и возвращает список валют в том же порядке.

Объяснение:

 (1+*)           # Add one to the interest rate
      ***        # Raise to the power of the year
          *      # And multiply by
           (*Z*1,29,493).sum      # The number of Knuts in the input
                            +|0   # And floor it
(                              ).polymod(29,17)   # Get the modulos after divmoding by 29 and 17

Я удивлен, что вы не придумали способ, позволяющий также подсчитать количество Кнутов / Серпов / Галеонов, подходящих для всех. Тогда это будет просто как, например, ************************* ;-)
user0721090601

@guifa Whatevers - это входные данные, поэтому их может быть только 3 (хотя я могу разделить ввод валюты еще на несколько *s, но больше байтов). Остальные из *s от умножения ( *) и экспоненты ( **)
Джо Кинг

Я имел в виду, если у вас есть коэффициенты конвертации (число 29/17) в них тоже. Но, конечно, это была шутка, потому что вам нужно использовать эти цифры более одного раза. Извините, если мой юмор не прошел
user0721090601

2

Желе , 29 байт

“¢×ø‘©×\
÷ȷ2‘*⁵×÷¢S×¢d®U1¦Ṫ€Ḟ

Полная программа, принимающая аргументы rate:; [Galleons, Sickles, Knuts]; years,
Печать [Galleons, Sickles, Knuts].

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

Этажи в конце всего срока.
÷ȷ2может быть удален, если мы можем принять ставку в процентах, а не в процентах.

Как?

“¢×ø‘©×\ - Link 1 multipliers: no arguments
“¢×ø‘    - list of code-age indices = [1,17,29]
     ©   - (copy this to the register for later use)
       \ - reduce by:
      ×  -   multiplication  = [1,17,493]

÷ȷ2‘*⁵×÷¢S×¢d®U1¦Ṫ€Ḟ - Main Link
 ȷ2                  - 10^2 = 100
÷                    - divide = rate/100
   ‘                 - increment = 1+rate/100
     ⁵               - 5th command line argument (3rd input) = years
    *                - exponentiate = (1+rate/100)^years --i.e. multiplicand
      ×              - multiply (by the borrowed amounts)
        ¢            - call last Link as a nilad
       ÷             - divide (all amounts in Galleons)
         S           - sum (total Galleons owed)
           ¢         - call last Link as a nilad
          ×          - multiply (total owed in each of Galleons, Sickles, Knuts)
             ®       - recall from register = [1,17,29]
            d        - divmod (vectorises) = [[G/1, G%1], [S/17, S^17], [K/17, K%17]]
              U1¦    - reverse first one = [[G%1, G/1], [S/17, S%17], [K/17, K%17]]
                 Ṫ€  - tail €ach = [G/1, S%17, K%17]
                   Ḟ - floor (vectorises)

2

Intel 8087 FPU в сборе, 86 байт

d9e8 d906 7f01 dec1 8b0e 8301 d9e8 d8c9 e2fc df06 7901 df06 8701 df06
7b01 df06 8501 df06 7d01 dec9 dec1 dec9 dec1 dec9 9bd9 2e89 01df 0687
01df 0685 01d9 c1de c9d9 c2d9 f8d8 f2df 1e7b 01d8 fadf 1e7d 01d9 c9d9
f8df 1e79 01

В разобранном виде и задокументировано:

; calculate P+I of loan from wizard
; input:
;   G: number of Galleons (mem16)
;   S: number of Sickles (mem16)
;   K: number of Knuts (mem16)
;   R: interest rate (float)
;   T: time in years (mem16)
;   GS: Galleons to Sickles exchange rate (mem16)
;   SK: Sickles to Knuts exchange rate (mem16)
; output:
;   G: number of Galleons (mem16)
;   S: number of Sickles (mem16)
;   K: number of Knuts (mem16)
WIZ_INT_CALC    MACRO   G, S, K, R, T, GS, SK
                LOCAL   LOOP_EXP
                    ; - calculate interet rate factor
    FLD1            ; load 1
    FLD   R         ; load interest rate
    FADD            ; ST = rate + 1
    MOV   CX, T     ; Exponent is count for loop
    FLD1            ; load 1 into ST as initial exponent value
LOOP_EXP:           ; loop calculate exponent
    FMUL  ST,ST(1)  ; multiply ST = ST * ST(1)
    LOOP  LOOP_EXP
                    ; - convert demonimations to Knuts
    FILD  K         ; load existing Knuts
    FILD  SK        ; load Sickles to Knuts rate 
    FILD  S         ; load existing Sickles
    FILD  GS        ; load Galleons-to-Sickles exchange rate
    FILD  G         ; load existing Galleons
    FMUL            ; multiply galleons to get sickles
    FADD            ; add existing sickles
    FMUL            ; multiply sickles to get knuts
    FADD            ; add existing knuts
    FMUL            ; calculate P+I (P in Knuts * Interest factor)
                    ; - redistribute demonimations to canonical form
    FLDCW  FRD      ; put FPU in round-down mode
    FILD   SK       ; load Sickles to Knuts rate
    FILD   GS       ; load Galleons-to-Sickles exchange rate
    FLD    ST(1)    ; copy Galleons-to-Sickles exchange rate to stack for later
    FMUL            ; multiply to get Galleons-to-Knuts rate
    FLD    ST(2)    ; push original total Knuts from ST(2) into ST (lost by FPREM)
    FPREM           ; get remainder
    FDIV   ST,ST(2) ; divide remainder to get number of Sickles
    FISTP  S        ; store Sickles to S
    FDIVR  ST,ST(2) ; divide to get number of Galleons
    FISTP  G        ; store Galleons to G
    FXCH            ; swap ST, ST(1) for FPREM
    FPREM           ; get remainder to get number of Knuts
    FISTP  K        ; store Knuts to K
        ENDM

Реализованный как MACRO (в основном функция), этот машинный код не зависит от ОС и использует для вычислений только процессор Intel 80x87 FPU / math.

Пример тестовой программы с выводом:

    FINIT           ; reset FPU

    WIZ_INT_CALC    G,S,K,R,T,GS,SK     ; do the "Wizardy"

    MOV  AX, K      ; display Knuts
    CALL OUTDEC     ; generic decimal output routine
    CALL NL         ; CRLF

    MOV  AX, S      ; display Sickles
    CALL OUTDEC     ; generic decimal output routine
    CALL NL         ; CRLF

    MOV  AX, G      ; display Galleons
    CALL OUTDEC     ; generic decimal output routine
    CALL NL         ; CRLF

    RET             ; return to DOS

K   DW  23          ; initial Kunts
S   DW  16          ; initial Sickles
G   DW  103         ; initial Galleons
R   DD  0.0725      ; interest rate
T   DW  3           ; time (years)
GS  DW  17          ; Galleons to Sickles exchange rate
SK  DW  29          ; Sickles to Knuts exchange rate
FRD DW  177FH       ; 8087 control word to round down

Выход

введите описание изображения здесь



1

Haskell , 73 байта

(g#s)k r n|(x,y)<-truncate((493*g+29*s+k)*(1+r)^n)%29=(x%17,y)
(%)=divMod

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

Спасибо @Laikoni за два байта.

Грязные приемы: количество монет на входе равно плавающей запятой ( Double), а количество монет на выходе - целое число ( Integer). В результате получается вложенная пара, ((Galleons, Sickles), Knotts)чтобы избежать сглаживания до тройной.

объяснение

-- Define a binary operator # that
-- takes the number of Galleons
-- and Slivers and produces a
-- function taking the number of
-- Knots, the rate, and the
-- number of years and producing
-- the result.
(g#s) k r n
   -- Calculate the initial value
   -- in Knotts, calculate the
   -- final value in Knotts,
   -- and divide to get the number
   -- of Galleons and the
   -- remainder.
  |(x,y)<-truncate((493*g+29*s+k)*(1+r)^n)%29
  -- Calculate the number of Slivers
  -- and remaining Knotts.
  =(x%17,y)
(%)=divMod

1
Сохраните два байта с (truncate$ ... )-> truncate( ... )и (g#s)k r nвместо c g s k r n.
Laikoni

@Laikoni, спасибо большое!
dfeuer

@Laikoni, я был бы очень признателен, если бы вы нашли мне пару байтов в codegolf.stackexchange.com/questions/55960/… если бы у вас было время.
Dfeuer

1
Я посмотрю на это, когда найду время. Между тем, я могу указать вам на наш чат на Хаскелле «Монады и Мужчины», а также на этот вопрос, который вам может понравиться, если вы используете полиглоты Hugs / GHC.
Laikoni


1

TI-BASIC (TI-84), 96 90 байт

:SetUpEditor C:Ans→∟C:∟C(1)+29∟C(2)+493∟C(3)→T:T(1+∟C(4))^∟C(5)→T:remainder(iPart(T),493→R:{remainder(R,29),iPart(R/29),iPart(T/493)}

Входные данные представляют Ansсобой список из 5 элементов: Кнуты, Серпы, Галеоны, Проценты (десятичные) и Время (годы).
Выход находится Ansи автоматически распечатывается после завершения программы.

Un-golfed:

:SetUpEditor C 
:Ans→∟C
:∟C(1)+29∟C(2)+493∟C(3)→T
:T(1+∟C(4))^∟C(5)→T
:remainder(iPart(T),493→R
:{remainder(R,29),iPart(R/29),iPart(T/493)}

Пример:

{32,2,5,0.05,5}
       {32 2 5 .05 5}
prgmCDGF1
            {12 10 6}

Объяснение:

:SetUpEditor C
:Ans→∟C

Новый список, ∟Cсоздается и Ansсохраняется в нем.

:∟C(1)+29∟C(2)+493∟C(3)→T

Кнуты, Серпы и Галеоны преобразуются в Кнуты и сохраняются в T.

:T(1+∟C(4))^∟C(5)→T

Принимает количество Кнутов и применяет сложный процент к нему.
Проценты начисляются здесь.

:remainder(iPart(T),493→R

Хранит I nteger Часть из по Tмодулю 493 в R. Используется для сокращения количества байтов.

:{remainder(R,29),iPart(R/29),iPart(T/493)}

Оценивает список из 3 предметов (Кнуты, Серпы и Галеоны). Список автоматически сохраняется в Ans.


Примечание. Счетчик байтов оценивается по количеству байтов, указанному в [MEM][2][7]. (список программ в ОЗУ), и вычитания количества символов в имени программы и дополнительных 8 байтов, используемых для программы:

103 - 5 - 8 = 90 байт


0

К, 46 байт

c:1000 17 29
t:{c\:{z(y*)/x}[c/:x;1+y%100;z]}

c сохранить список для преобразования базы

t это функция, которая рассчитывает общую сумму

Пример использования:

t[103 16 23;7.25;3]

пишет (128;4;24.29209)

Объяснение:

  • c/:x преобразовать список (галеон; серп; кнут) в куц

  • 1+y%100 рассчитать процентную ставку (пример 1.0725 для 7.25% ставки)

  • Лямбда {z(y*)\x}выполняет свою работу: повторяет 3 раза, применяя интерес * main, и возвращает final main.

  • c\: генерирует галеон, серпы, кнуты из кнутов

ПРИМЕЧАНИЕ. Если вам не нужна функция имен, мы можем использовать лямбду, экономя 2 байта {c\:{z(y*)/x}[c/:x;1+y%100;z]}inputArgs


0

C # (интерактивный компилятор Visual C #) , 86 байт

(a,b,c)=>((k=(int)((a.a*493+a.b*29+a.c)*Math.Pow(1+b,c)))/493,(k%=493)/29,k%29);int k;

Принимает в качестве именованного кортежа с 3 значениями, представляющими кнуты, серпы и галеоны, и процентной ставкой в ​​двойном размере (не в процентах). Мне бы очень хотелось, чтобы в C # был оператор экспоненты. Math.Pow слишком длинный :(

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


0

Пакет, 171 байт

@set i=%4
@set/af=0,i=8*%i:.=,f=%,f*=8
@set/ai+=%f:~,1%,k=%1*493+%2*29+%3
@for /l %%y in (1,1,%5)do @set/ak+=k*i/800
@set/ag=k/493,s=k/29%%17,k%%=29
@echo %g% %s% %k%

Принимает данные в качестве аргументов командной строки в следующем порядке: галеоны, серпы, кнуты, проценты, годы. Проценты - это проценты, но они выражены без знака%. Обрезается после каждого года. Выход в порядке галеонов, серпов, кнутов. Поддерживает не менее 5000 галеонов. Объяснение:

@set i=%4
@set/af=0,i=8*%i:.=,f=%,f*=8

Пакет имеет только целочисленную арифметику. К счастью, процентная ставка всегда кратна 0.125. Мы начнем с разделения на десятичную точку, чтобы она iстала целой частью процентной ставки и fдесятичной дроби. Затем они умножаются на 8. Теперь первая цифра f- это число восьмых в процентной ставке.

@set/ai+=%f:~,1%,k=%1*493+%2*29+%3

Затем это извлекается с использованием нарезки строк и добавляется для получения процентной ставки в 1/800. Количество кнутов также рассчитывается.

@for /l %%y in (1,1,%5)do @set/ak+=k*i/800

Рассчитать и добавить на каждый год интерес.

@set/ag=k/493,s=k/29%%17,k%%=29
@echo %g% %s% %k%

Конвертировать обратно в галеоны и серпы.


0

05AB1E (legacy) , 24 байта

>Im•1ýÑ•3L£I*O*ï29‰ć17‰ì

Порт ответа @JoKing 's Perl 6 , так что не забудьте также поддержать его, если вам нравится этот ответ!

Я использую устаревшую версию из-за ошибки в новой версии, £которая не работает с целыми числами, поэтому явное приведение к строке §(между вторым и3 ) (до тех пор, пока ошибка не будет исправлена).

Принимает интерес в виде десятичного числа, за которым следует год, за которым следует список [Кнуты, Серпы, Галеоны].

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

Объяснение:

>                      # Increase the (implicit) interest decimal by 1
                       #  i.e. 0.0725 → 1.0725
 Im                    # Take this to the power of the year input
                       #  i.e. 1.0725 and 3 → 1.233...
1ýÑ•                  # Push compressed integer 119493
     3L                # Push list [1,2,3]
       £               # Split the integer into parts of that size: [1,19,493]
        I*             # Multiply it with the input-list
                       #  i.e. [1,19,493] * [23,16,103] → [23,464,50779]
          O            # Take the sum of this list
                       #  i.e. [23,464,50779] → 51266
           *           # Multiply it by the earlier calculated number
                       #  i.e. 51266 * 1.233... → 63244.292...
            ï          # Cast to integer, truncating the decimal values
                       #  i.e. 63244.292... → 63244
             29       # Take the divmod 29
                       #  i.e. 63244 → [2180,24]
                ć      # Extract the head; pushing the remainder-list and head separately
                       #  i.e. [2180,24] → [24] and 2180
                 17   # Take the divmod 17 on this head
                       #  i.e. 2180 → [128,4]
                    ì  # And prepend this list in front of the remainder-list
                       #  i.e. [24] and [128,4] → [128,4,24]
                       # (which is output implicitly as result)

Посмотрите эту подсказку 05AB1E (раздел Как сжать большие целые числа? ), Чтобы понять, почему •1ýÑ•это так 119493.


0

APL (NARS), 37 символов, 74 байта

{(x y z)←⍵⋄⌊¨a⊤(z⊥⍨a←0 17 29)×x*⍨1+y}

перевод очень хорошего и очень маленького байтового решения APL пользователем Graham в решение, которое использует одну функцию вместо стандартного ввода ... test и как его использовать:

  f←{(x y z)←⍵⋄⌊¨a⊤(z⊥⍨a←0 17 29)×x*⍨1+y}
  f 3 0.0725 (103 16 23)
128 4 24

(я не говорю, что понял алгоритм)


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