Como NÃO reduzir frações

13

Reduzindo frações da maneira errada

Neste desafio do código-golfe, você precisa encontrar frações que podem ser reduzidas da maneira errada, mas que acabam no mesmo número.

Nota: reduzir frações da maneira errada tem aqui uma definição exata, veja detalhes.

Exemplo:

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

Claro que você não pode simplesmente acertar os 6es, mas aqui você ainda terá o valor correto. Neste desafio, você precisa encontrar exemplos como este.

Detalhes

Você precisa escrever uma função / programa que aceite um número inteiro positivo ncomo entrada e produz / retorna uma lista / matriz das frações no formato
numerator1,denominator1,numerator2,denominator2,...

O programa tem que descobrir por cada fracção a/bcom a+b=ne a,b>0se ele pode ser reduzido de forma errada . (Não importa se ele pode ser reduzido da maneira convencional ou se existem muitas possibilidades de reduções, basta que seja possível reduzi-la da maneira errada de pelo menos uma maneira.)

Definição da maneira errada: Uma fração pode ser reduzida da maneira errada se e somente se a mesma sequência de dígitos sucessivos aparecer em aeb e se o valor da fração permanecer o mesmo se você remover a substring.

Exemplo: 1536/353 pode ser 'reduzido' para 16/3, mas esses dois valores não são iguais, portanto, você não pode reduzir essa fração da maneira errada .

Observe que essa definição de redução da maneira errada também pode incluir frações reduzidas da maneira correta: 110/10 = 11/1está dentro da definição de redução da maneira errada, mesmo que seja uma etapa válida.

Pontuação

O menor número de bytes vence. Você pode escrever uma função ou programa que aceita um número inteiro e retorna uma matriz ou um programa que usa stdin / stdout ou pode considerar n salvo em uma variável e no final do programa a lista deve ser salva em outra variável.

Casos de teste

Inclua os seguintes casos de teste (diga-me quais devo adicionar, não tenho idéia de quantas dessas frações existem / quantos exemplos esperar)

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
flawr
fonte
3
Considere definir um termo para "o caminho errado", como "pateta" ou "esquisita". Acho que o post seria mais fácil de entender, porque os leitores imediatamente entendem que deve haver uma definição para o termo.
Michael Easter
3
E se houver várias maneiras de reduzir uma fração e apenas algumas delas estiverem erradas? 1010/10 = 101/1 && 1010/10 /= 110/1
John Dvorak
1
Variante de projecteuler.net/problem=33 ?
user80551
1
O seu segundo caso de teste ( n=147) está incorreta: 49/89 != 4/8.
Beta Decay
1
Se houver mais de uma maneira de reduzir uma fração, podemos incluí-la várias vezes no conjunto de resultados?
John Dvorak

Respostas:

3

Python 2-181 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],[])

a entrada deve ser armazenada n, a saída será armazenada l.

Casos de teste:

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]

Se duplicatas na saída forem proibidas, elas terão 10 caracteres a mais:

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
fonte
3

Haskell, 207 206 (209?) Caracteres

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]

Se não for permitido retornar a mesma proporção mais de uma vez (400/400 = 40/40 = 4/4), use f n=nub[...para filtrá-los.

Retorna uma lista de pares. Uma lista de pares de dois elementos custa o mesmo. Uma lista de frações reais exigiria importação Data.Ratioou qualificação completa Data.Ratio.%(que também colide com a %função definida aqui)

casos de teste (com 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)]

ungolfed e comentou :

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
fonte
você pode mudar ';' para novas linhas (no código de golfe)? isso não altera a contagem de bytes e torna o código muito mais legível
haskeller orgulhoso
@proudhaskeller Isso é deliberado; Eu gosto de ter menos linhas no código do golfe. Além disso, os comprimentos das linhas são mais equilibrados dessa maneira. Você acha que eu deveria mudar?
John Dvorak
fazer o que quiser, mas eu gostaria que as linhas a serem espalhados por isso eu seria capaz de ler o código melhor (em vez de recorrer ao código ungolfed)
haskeller orgulhoso
Você está bem com a versão atual? Eu não posso dividir a última linha, infelizmente (exceto em espaços, que mataria a legibilidade)
John Dvorak
como eu disse, faça o que quiser
proud 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
fonte
1

Python 3-302

Nota: Devido a dificuldades de análise, não há frações com o número 0 em (portanto, nenhuma fração é calculada usando o método correto).

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])

Com n = 80:

[[64, 16]]

Com n = 147

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

Com 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]]
Beta Decay
fonte
Para n=80isso [[64, 16], [65, 26]], mas obviamente 65 + 26 = 91 > 80.
Ingo Bürk
Transformar todos os ifs em um único grande ifcom ands conectando todas as condições? Economiza alguns caracteres, eu acho.
Soham Chowdhury
@ Soham Sim, obrigado!
Decay Beta
Você também pode incluir os casos de teste que eu adicionei? (E você poderia talvez ver se você encontrar alguns casos de teste interessantes Devo acrescentar também?)
flawr
2
Onde estão 10/70, 20/60e 30/50?
John Dvorak