Dochód o zmiennych cenach!

16

Wprowadzenie i zaliczenie

Załóżmy, że jesteś barmanem. W twoim barze jest wielu szczęśliwych ludzi, ale wielu z nich pije tylko ten sam napój i za mało dla twojego smaku i chcesz to zmienić. Wprowadzasz więc system, w którym cena napoju jest zmienna, w zależności od tego, ile już zostało sprzedanych, ale nigdy nie jest droższe niż pewne progi. Z jakiegoś dziwnego powodu zawsze zapominasz o właściwym śledzeniu wszystkich sprzedawanych napojów i cen, dlatego musisz pomyśleć o krótkim (= niezapomnianym!) Fragmencie kodu, który robi matematykę dla ciebie biorąc pod uwagę ilość wypitych napojów.

Wyzwanie to pojawiło się już podczas egzaminu śródokresowego w 2012 r. Na kursie programowania funkcjonalnego na moim uniwersytecie i mam zgodę profesora na opublikowanie go tutaj. Dostaliśmy przykładowe rozwiązanie w języku egzaminu.

Wejście

Twój wkład to lista ciągów znaków, które nie zawierają spacji - są to nazwy sprzedawanych napojów. Wprowadź dane wejściowe, używając preferowanej, ogólnie akceptowanej metody wprowadzania danych.

Wynik

Twój wynik będzie pojedynczą liczbą - to przychód, który wygenerowałeś dziś wieczorem. Podaj dane wyjściowe przy użyciu preferowanej, ogólnie akceptowanej metody wydruku.

Co robić?

Dotyczy to każdego drinka z osobna:

  • Cena wywoławcza wynosi 10.
  • Za każdym razem, gdy napój jest kupowany, jego cena jest podwyższana o 1 dla następnego nabywcy.
  • Maksymalna cena to 50. Jeśli napój został kupiony za 50, nowa cena ponownie wyniesie 10.

Twoim zadaniem jest znaleźć całkowity dochód wygenerowany przez listę wejściową napojów przy powyższych zasadach.


Jeśli zastanawiasz się: „50 dolców jest naprawdę cholernie drogie za drinka!”, To 50 dolców za decy, więc 50 * 0,1 * Jednostka, ale zdecydowałem się na 10-50, aby nie wykluczać języków bez arytmetyka zmiennoprzecinkowa.

Kto wygrywa?

To jest , więc wygrywa najkrótszy kod w bajtach! Obowiązują standardowe zasady.

Potencjalne narożne skrzynki

Jeżeli lista wejściowa jest pusta, wartość wyjściowa powinna wynosić 0.
Nie można zakładać, że lista wejściowa jest posortowana według napoju.

Przykłady

[] -> 0
["A"] -> 10
["A","B"] -> 20
["A","A","B"] -> 31
["A","B","A"] -> 31
["A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A"] -> 1240
["A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","B","B","B","C","C","D"] -> 1304 
["D","A","A","C","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","B","B","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","B","C"] -> 1304
["A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","B","B","B","C","C","D","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A"] -> 1304
SEJPM
źródło
1
Propozycje na pytanie profesora przed opublikowaniem, całkiem ruch OG.
Magic Octopus Urn

Odpowiedzi:

4

JavaScript (ES6), 50 bajtów

a=>a.map(x=>t+=d[x]=d[x]<50?d[x]+1:10,t=0,d={})&&t
ETHprodukcje
źródło
Gdzie inicjujesz d[x]do 10?
Tytus
@Titus Jeśli d[x]nie został ustawiony, jest undefined; powoduje to, że d[x]<50return jest fałszywy, więc d[x]=d[x]<50?d[x]+1:10ustawia się d[x]na 10.
ETHproductions
I keeü zapominając, że JS ma undefined. :)
Tytus
4

Python 2, 79 74 54 48 bajtów

Ogromny wzrost liczby bajtów poprzez ponowne przemyślenie problemu. Chciałbym się pozbyć intobsady, ale mój mózg nie działa . Korzystając z, l.pop()aby uniknąć dwukrotnego przycinania listy i dobrej starej rekurencji lambda :)

f=lambda l:l and l.count(l.pop())%41+10+f(l)or 0

dzięki Jonathanowi Allanowi za uratowanie 6 bajtów :)

Moja stara 54-bajtowa wersja, z której byłem dość dumny :)

f=lambda l:int(l>[])and~-l.count(l[0])%41+10+f(l[1:])
Kade
źródło
...l>[]and 1*~...aby zapisać te 3 bajty, o których wiedziałeś, że możesz.
Jonathan Allan,
W rzeczywistości o 1 mniej z:f=lambda l:l and~-l.count(l[0])%41+10+f(l[1:])or 0
Jonathan Allan
Oooh i jeszcze dwie osoby z:f=lambda l:l and l.count(l.pop())%41+10+f(l)or 0
Jonathan Allan,
@JonathanAllan dzięki za wskazówki! Wkrótce zaktualizuję swój post :)
Kade
2

Pyth, 15 bajtów

ssm<*lQ}T50/Qd{

Program, który pobiera dane z listy i drukuje wynik.

Zestaw testowy (pierwszy wiersz umożliwiający wielokrotne wprowadzanie danych)

Jak to działa

ssm<*lQ}T50/Qd{   Program. Input: Q
ssm<*lQ}T50/Qd{Q  Implicit input fill
              {Q  Deduplicate Q
  m               Map over that with variable d:
       }T50        Yield [10, 11, 12, ..., 48, 49, 50]
    *lQ            Repeat len(Q) times
   <       /Qd     First Q.count(d) elements of that
 s                Flatten
s                 Sum
                  Implicitly print
TheBikingViking
źródło
2

Galaretka , 14 11 10 bajtów

50⁵rṁЀĠSS

TryItOnline!

W jaki sposób?

50⁵rṁЀĠSS - Main link: list of drink names                e.g. ['d', 'a', 'b', 'a', 'c']
       Ġ   - group indices by values                       e.g. [[2, 4], [3], [5], [1]]
  ⁵        - 10
50         - 50
   r       - inclusive range, i.e. [10, 11, 12, ..., 48, 49, 50]
    ṁЀ    - mould left (the range) like €ach of right(Ð)  e.g. [[10, 11], [10], [10], [10]]
                 note: moulding wraps, so 42 items becomes [10, 11, 12, ..., 48, 49, 50, 10]
        S  - sum (vectorises)                              e.g. [40, 11]
         S - sum                                           e.g. 51
Jonathan Allan
źródło
2

05AB1E , 16 15 bajtów

Dzięki Emignie za uratowanie bajtu!

ÎÙv¹y¢L<41%T+OO

Wykorzystuje kodowanie CP-1252 . Wypróbuj online!

Adnan
źródło
ÎÙv¹y¢L<41%T+OOpowinien działać na zapisany 1 bajt
Emigna,
@Emigna To miło! Dzięki :)
Adnan
1

Perl 41 bajtów

Obejmuje +1 dla -p

$\+=$H{$_}+=$H{$_}?$H{$_}>49?-40:1:10;}{

Bierze wkład w nowe linie.

Zwiększa wartość skrótu o: 10 jeśli jest undef, -40jeśli jest > 49tj. 50Lub w 1inny sposób. To jest następnie dodawane do$\ separatora wyjściowego, który -pdrukuje.

Przykład:

$ echo -e 'A\nB\nA' | perl -pe '$\+=$H{$_}+=$H{$_}?$H{$_}>49?-40:1:10;}{'
31
Riley
źródło
1

05AB1E , 13 bajtów

{.¡€gL<41%T+O

Wyjaśnienie

["A","B","A"] użyty jako przykład.

{               # sort input
                # STACK: ["A","A","B"]
 .¡             # split on different
                # STACK: [["A","A"],["B"]]
   €g           # length of each sublist
                # STACK: [2,1]
     L          # range [1 ... x] (vectorized)
                # STACK: [1,2,1]
      <         # decrease by 1
                # STACK: [0,1,0]
       41%      # mod 41
                # STACK: [0,1,0]
          T+    # add 10
                # STACK: [10,11,10]
            O   # sum
                # OUTPUT: 31
Emigna
źródło
1

C ++ 14, 105 bajtów

Jako ogólna nienazwana lambda powracająca poprzez parametr referencyjny. Wymaga, aby dane wejściowe były kontenerem stringtego push_backtypu vector<string>.

Używając %41+10sztuczki z odpowiedzi Kade'a na Python .

[](auto X,int&r){r=0;decltype(X)P;for(auto x:X){int d=0;for(auto p:P)d+=x==p;r+=d%41+10;P.push_back(x);}}

Tworzy pusty pojemnik Pjako pamięć, która została już obsłużona. Cena jest obliczana poprzez zliczenie xw P.

Niegolfowane i użytkowanie:

#include<iostream>
#include<vector>
#include<string>

using namespace std;

auto f=
[](auto X, int& r){
  r = 0;
  decltype(X) P;
  for (auto x:X){
    int d = 0;
    for (auto p:P)
      d += x==p;
    r += d % 41 + 10;
    P.push_back(x);
  }
}
;

int main(){
 int r;
 vector<string> V;
 f(V,r);cout << r << endl;
 V={"A"};
 f(V,r);cout << r << endl;
 V={"A","B"};
 f(V,r);cout << r << endl;
 V={"A","B","C"};
 f(V,r);cout << r << endl;
 V={"A","A"};
 f(V,r);cout << r << endl;
 V={"A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A"};
 f(V,r);cout << r << endl;
 V={"A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","B","B","B","C","C","D"};
 f(V,r);cout << r << endl;
 V={"A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","B","C"};
 f(V,r);cout << r << endl;
}
Karl Napf
źródło
0

Mathematica, 64 bajty

Wydaje się, że powinien być krótszy.

Tr[(19+#)#/2&/@(Length/@Gather@#//.z_/;z>41:>Sequence[41,z-41])]&

Length/@Gather@#liczy powtórzenia każdego napoju. //.z_/;z>41:>Sequence[41,z-41]dzieli dowolną liczbę całkowitą zprzekraczającą 41 w tym na 41i z-41, aby odzwierciedlić spadek ceny. Następnie każdy z liczników jest podłączany do formuły (19+#)#/2, która jest całkowitym kosztem #napojów tak długo, jak #najwyżej 41. Wreszcie, Trpodsumowuje te koszty.

Greg Martin
źródło
0

k, 22 bajtów

Argumentem może być dowolna lista - ciągi, cyfry itp.

{+/,/10+(#:'=x)#\:!41}

qTłumaczenie jest łatwiejsze do odczytania:

{sum raze 10+(count each group x)#\:til 41}
skeevey
źródło
0

C #, 193 bajtów + 33

Dodatkowe 33 bajty dla using System.Collections.Generic;

void m(string[]a){int t=0;Dictionary<string,int>v=new Dictionary<string,int>();foreach(string s in a){if(v.ContainsKey(s)){v[s]=v[s]==50?10:v[s]+1;}else{v.Add(s,10);}t+=v[s];}Console.WriteLine(t);}

Jestem pewien, że można to pograć w zapomnienie, Słowniki zdecydowanie nie są najlepszym sposobem na zrobienie tego i prawdopodobnie mógłbym wprowadzić trójkę do mojego if. Poza tym myślę, że jest w porządku!

Przykłady:

a = {"A", "A", "A", "B", "B", "C"};
//output = 64

a = {"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A",, "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A", "A" ,"A" "A" ,"A", "A" ,"A", "B", "B", "C"};
//output 727

Nie golfił

void m(string[] a)
{
    int t=0;
    Dictionary<string,int> v = new Dictionary<string,int>();
    foreach(string s in a)
    {
        if(v.ContainsKey(s))
        {
            v[s]=v[s]==50?10:v[s]+1;
        }
        else
        {
            v.Add(s,10);
        }
        t+=v[s];
    }
    Console.Write(t);
}
Alfie Goodacre
źródło
0

Clojure, 79 bajtów

#(apply +(mapcat(fn[l](for[i(range l)](+(mod i 41)10)))(vals(frequencies %)))))

Liczy częstotliwości napojów, a następnie oblicza cenę podstawową jako 10 + (i % 41). mapcatłączy je i apply +oblicza sumę.

NikoNyrh
źródło
0

PHP, 47 bajtów

while($k=$argv[++$i])$s+=10+$p[$k]++%41;echo$s;

pobiera dane wejściowe z argumentów wiersza poleceń; biegać z -r.

Tytus
źródło