Jak NIE zmniejszać ułamków

13

Niewłaściwe zmniejszenie frakcji

W tym wyzwaniu golfa musisz znaleźć frakcje, które można zmniejszyć w niewłaściwy sposób, ale wciąż kończą się tą samą liczbą.

Uwaga: zmniejszenie ułamków w niewłaściwy sposób ma tutaj dokładną definicję, zobacz szczegóły.

Przykład:

64/16 = 6 4/1 6 = 4/1 = 4

Oczywiście nie możesz po prostu trafić obu 6, ale tutaj nadal masz prawidłową wartość. W tym wyzwaniu musisz znaleźć takie przykłady.

Detale

Musisz napisać funkcję / program, który przyjmuje jedną dodatnią liczbę całkowitą njako dane wejściowe i wyjściowe / zwraca listę / tablicę ułamków w formacie
numerator1,denominator1,numerator2,denominator2,...

Program ma znaleźć się na każdej frakcji a/bz a+b=ni a,b>0czy może ona zostać zmniejszona w niewłaściwy sposób . (Nie ma znaczenia, czy można to zmniejszyć w sposób konwencjonalny, czy też istnieje wiele możliwości redukcji, musi być możliwe zmniejszenie go w niewłaściwy sposób przynajmniej na jeden sposób).

Definicja niewłaściwego sposobu: Ułamek można zmniejszyć w niewłaściwy sposób tylko wtedy, gdy ta sama sekwencja kolejnych cyfr pojawia się w aib oraz jeśli wartość ułamka pozostaje taka sama, jeśli usuniesz podłańcuch.

Przykład: 1536/353 można „zredukować” do 16/3, ale te dwie wartości nie są równe, więc nie można zmniejszyć tej frakcji w niewłaściwy sposób .

Zauważ, że ta definicja zmniejszania niewłaściwego sposobu może również obejmować ułamki, które są zmniejszane we właściwy sposób: 110/10 = 11/1mieści się w definicji zmniejszania niewłaściwego sposobu, mimo że jest to właściwy krok.

Punktacja

Wygrywa najmniejsza liczba bajtów. Możesz napisać funkcję lub program, który akceptuje liczbę całkowitą i zwraca tablicę lub program, który używa stdin / stdout, lub możesz rozważyć n zapisane w zmiennej, a na końcu programu lista musi zostać zapisana w innej zmiennej.

Przypadki testowe

Podaj następujące przypadki testowe (Powiedz mi, które powinienem dodać, nie mam pojęcia, ile jest tych ułamków / ile przykładów można się spodziewać)

n=80 (64/16 should be in this list)
n=147 (98/49 should be in this list)
n=500 (294/196 should be in this list) WRONG since 294+196 != 500 Thanks Falko
wada
źródło
3
Zastanów się nad zdefiniowaniem terminu „niewłaściwy sposób”, na przykład „głupkowaty” lub „dziwaczny”. Myślę, że post byłby łatwiejszy do zrozumienia, ponieważ czytelnicy od razu myślą, że musi istnieć definicja tego terminu.
Michael Wielkanoc
3
Co zrobić, jeśli istnieje wiele sposobów na zmniejszenie ułamka i tylko niektóre z nich są błędne? 1010/10 = 101/1 && 1010/10 /= 110/1
John Dvorak
1
Wariant projecteuler.net/problem=33 ?
user80551
1
Twój drugi przypadek testowy ( n=147) jest nieprawidłowy: 49/89 != 4/8.
Beta Decay
1
Jeśli istnieje więcej niż jeden sposób na zmniejszenie ułamka, czy możemy uwzględnić go wiele razy w zestawie wyników?
John Dvorak

Odpowiedzi:

3

Python 2 - 183 180

r=range
s=lambda a:[(a[i:j],int(a[:i]+a[j:]))for i in r(len(a))for j in r(i+1,len(a)+(i>0))]
l=sum([[a,n-a]for a in r(n)for p,x in s(`a`)for q,y in s(`n-a`)if(n-a)*x==a*y<p==q],[])

wejście musi być zapisane n, wyjście zostanie zapisane l.

Przypadki testowe:

n = 80:

[10, 70, 16, 64, 20, 60, 30, 50, 40, 40, 40, 40, 50, 30, 60, 20, 64, 16, 70, 10]

n = 147:

[49, 98, 98, 49]

n = 490:

[10, 480, 20, 470, 30, 460, 40, 450, 50, 440, 60, 430, 70, 420, 80, 410, 90, 400, 90, 400, 98, 392, 100, 390, 100, 390, 110, 380, 120, 370, 130, 360, 140, 350, 150, 340, 160, 330, 170, 320, 180, 310, 190, 300, 190, 300, 196, 294, 200, 290, 200, 290, 210, 280, 220, 270, 230, 260, 240, 250, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 250, 240, 260, 230, 270, 220, 280, 210, 290, 200, 290, 200, 294, 196, 300, 190, 300, 190, 310, 180, 320, 170, 330, 160, 340, 150, 350, 140, 360, 130, 370, 120, 380, 110, 390, 100, 390, 100, 392, 98, 400, 90, 400, 90, 410, 80, 420, 70, 430, 60, 440, 50, 450, 40, 460, 30, 470, 20, 480, 10]

Jeśli duplikaty danych wyjściowych są zabronione, stają się dłuższe o 10 znaków:

r=range
s=lambda a:[(a[i:j],int(a[:i]+a[j:]))for i in r(len(a))for j in r(i+1,len(a)+(i>0))]
l=sum(map(list,{(a,n-a)for a in r(n)for p,x in s(`a`)for q,y in s(`n-a`)if(n-a)*x==a*y<p==q}),[])
Wrzlprmft
źródło
3

Haskell, 207 206 (209?) Znaków

import Data.List
x![]=[x];(w:x)!(y:z)|w==y=x!z;_!_=[]
a@(w:x)%b=a!b++[w:e|e<-x%b];a%b=a!b
h=show
f n=[(c,n-c)|c<-[1..n-1],i<-inits$h c,s<-init$tails i,s/=h c,a<-h c%s,b<-h(n-c)%s,read a*(n-c)==read('0':b)*c]

Jeśli nie można zwrócić tego samego współczynnika więcej niż jeden raz (400/400 = 40/40 = 4/4), użyj, f n=nub[...aby je odfiltrować.

Zwraca listę par. Lista par dwuelementowych kosztuje tyle samo. Lista rzeczywistych ułamków wymagałaby importu Data.Ratiolub pełnej kwalifikacji Data.Ratio.%(co również koliduje ze %zdefiniowaną tutaj funkcją)

przypadki testowe (z nub):

Prelude Data.List> f 80
[(10,70),(16,64),(20,60),(30,50),(40,40),(50,30),(60,20),(64,16),(70,10)]
Prelude Data.List> f 147
[(49,98),(98,49)]
Prelude Data.List> f 500
[(10,490),(20,480),(30,470),(40,460),(50,450),(60,440),(70,430),(80,420),(90,410
),(100,400),(110,390),(120,380),(130,370),(140,360),(150,350),(160,340),(170,330
),(180,320),(190,310),(200,300),(210,290),(220,280),(230,270),(240,260),(250,250
),(260,240),(270,230),(280,220),(290,210),(300,200),(310,190),(320,180),(330,170
),(340,160),(350,150),(360,140),(370,130),(380,120),(390,110),(400,100),(410,90)
,(420,80),(430,70),(440,60),(450,50),(460,40),(470,30),(480,20),(490,10)]

niepolubił i skomentował :

import Data.List

-- haystack ! needle - the haystack with the needle removed, wrapped in a single-element list
--                       or an empty array if the haystack does not start with the needle

x ! [] = [x]                        -- case: empty needle = match with the full haystack left
(h:hs) ! (n:ns) | h == n = hs ! ns  -- case: needle and haystack match
_ ! _ = []                          -- case: no match

-- haystack % needle - the haystack with the needle removed 
--                       for all positions of the needle in the haystack

a@(h:hs) % b = a ! b ++ map (h:) (hs%b) -- either remove the needle here, or elsewhere
a % b = a                               -- empty haystack cannot be popped

-- f - the function we are interested in

f total = [ (num, total - num) 
          | num   <- [1 .. total-1],            -- for each numerator in range
            i     <- inits $ show num,          -- for each postfix of the numerator
            sub   <- init $ tails i,            -- for each prefix of the postfix except the last (empty) one
            sub /= show num,                    -- that isn't equal to the numerator
            reNum <- show num % sub,            -- remove the substring from the numerator
            reDiv <- show (total - num) % sub,  -- as well as from the denominator.

                                                -- the resulting ratios must be equal by value:
            (read reNum) ^ (total - num) == (read '0':reDiv) * num]
John Dvorak
źródło
możesz zmienić ';' do nowych linii (w kodzie golfowym)? nie zmienia liczby bajtów i sprawia, że ​​kod jest znacznie bardziej czytelny
dumny haskeller
@proudhaskeller To celowe; Lubię mieć mniej linii w kodzie golfowym. Również długości linii są w ten sposób bardziej zrównoważone. Myślisz, że powinienem się zmienić?
John Dvorak
rób co chcesz, ale chciałbym, aby linie były rozłożone, aby móc lepiej odczytać kod (zamiast uciekać się do kodu bez golfa)
dumny haskeller
Czy wszystko w porządku z obecną wersją? Niestety nie mogę podzielić ostatniego wiersza (z wyjątkiem spacji, które zabiłyby czytelność)
John Dvorak
jak powiedziałem, rób co chcesz
dumny haskeller
1

Python 2 - 236

n=input()
r=range
f=float
l=len
for a in r(n):
 A=`a`;B=`n-a`
 for i in r(l(A)):
  for j in r(i+1,l(A)+1):
   for u in r(l(B)):
    C=A[:i]+A[j:];D=B[:u]+B[u+j-i:]
    if A[i:j]==B[u:u+j-i]and l(C)*l(D)and f(C)==f(A)/f(B)*f(D):print A,B
Falko
źródło
1

Python 3 - 302

Uwaga: Z powodu trudności z parsowaniem nie ma ułamków z liczbą 0 w (więc ułamki nie są obliczane przy użyciu poprawnej metody).

n=int(input());s=str;r=range
print([[a,b]for a in r(1,n)for b in r(1,a)for i in r(1,n)if i!=a and i!=b and s(i)in s(a)and s(i)in s(b)and s(a).count(s(i))<len(s(a))and s(b).count(s(i))<len(s(b))and not'0'in s(a)and not'0'in s(b)and eval(s(a).replace(s(i),'')+'/'+s(b).replace(s(i),''))==a/b and a+b<=n])

Przy n = 80:

[[64, 16]]

Przy n = 147

[[64, 16], [65, 26], [95, 19], [98, 49]]

Przy n = 500

[[64, 16], [65, 26], [95, 19], [98, 49], [136, 34], [192, 96], [194, 97], [195, 39], [196, 49], [196, 98], [231, 132], [238, 34], [238, 136], [242, 143], [253, 154], [264, 165], [268, 67], [275, 176], [286, 187], [291, 97], [291, 194], [294, 49], [294, 98], [294, 196], [295, 59], [297, 198], [298, 149], [325, 13], [341, 143], [345, 138], [392, 49], [392, 98], [395, 79]]
Rozpad beta
źródło
Do n=80tego odbitki [[64, 16], [65, 26]], ale oczywiście 65 + 26 = 91 > 80.
Ingo Bürk
Zmienić wszystkie ifs w jedno duże ifdzięki ands łączącym wszystkie warunki? Myślę, że oszczędza sporo znaków.
Soham Chowdhury,
@Soham Tak, dziękuję!
Beta Decay
Czy możesz również dołączyć testowane przeze mnie skrzynki testowe? (A może mógłbyś zobaczyć, czy znajdziesz jakieś interesujące przypadki testowe, które powinienem dodać?)
flawr
2
Gdzie są 10/70, 20/60i 30/50?
John Dvorak