Sua empresa está apenas começando um projeto e, pela primeira vez, você decidiu usar um estilo de código de programação funcional. No entanto, seu chefe é realmente indiferente e não deseja usar funções internas e requer que você implemente as funções principais. Em particular, você precisa escrever as funções: Map
, Nest
, Apply
, Range
, Fold
e Table
em uma língua da sua escolha. O chefe é um homem muito ocupado, e ele quer ter os programas o mais curto possível, para não perder tempo lendo. Ele também gostaria que você não usasse loops, portanto, você terá uma redução de 10% na contagem de bytes por não usar loops.
Os requisitos detalhados das funções estão abaixo:
Mapa
A Map
função usa dois parâmetros: f
e list
onde f
é uma função e list
é uma lista de valores. Ele deve retornar o f
aplicado a cada elemento de list
. Portanto, ele funcionará como tal:
Map(f,{a,b,c})
retorna
{ f(a), f(b), f(c) }
e
Map(f, {{a,b},{b,c}})
retorna
{ f({a,b}), f({b,c})}
Ninho
A Nest
função usa três parâmetros, bem como: f
, arg
, times
onde f
é uma função, arg
é o seu argumento inicial, e times
é quantas vezes a função é aplicada. Deve retornar uma expressão com tempos f
aplicados times
para arg
. Portanto, ele funcionará como tal:
Nest(f, x, 3)
retorna
f(f(f(x)))
e
Nest(f, {a,b}, 3)
retorna
f(f(f({a,b})))
Aplique
A Apply
função usa dois parâmetros: f
e args
onde f
é uma função e args
uma lista. Deve aplicar f
- se ao args
. Assim sendo:
Apply(f, {a,b,c})
retorna
f(a,b,c)
Alcance
A Range
função pega um número inteiro r
e gera os números inteiros até esse número. Assim sendo:
Range(5)
retorna
{ 1, 2, 3, 4, 5}
Dobra
A Fold
função usa três parâmetros f
, arg
, others
onde f
é uma função, arg
é um parâmetro simples, e others
uma lista. Funcionará assim:
Fold(f, x, {a, b, c, d})
retorna
f(f(f(f(x,a),b),c),d)
Tabela
As funções da tabela devem ter uma função f
e um parâmetro chamado iterator
no formato: {iMin, iMax}
where iMin
e iMax
são números inteiros. Você deve aplicar f
no intervalo especificado. Assim sendo:
Table(f, {0, 5})
retorna
{f(0), f(1), f(2), f(3), f(4), f(5)}
Eu usei a definição dessas funções na página de programação funcional do Mathematica ; portanto, vá para lá se precisar de mais orientações. Observe que você não precisará implementar toda a versão das funções mostradas nessa página, mas apenas as escritas nesta postagem.
As brechas padrão não são permitidas como de costume.
Caso seu idioma não permita que funções sejam passadas como argumentos, você precisará implementar esse recurso e adicioná-lo à sua resposta. No entanto, a contagem de bytes desta operação não será adicionada ao total.
Este é o código de golfe, portanto o código mais curto vence. Boa sorte!!!
fonte
Table
funciona aqui. Seu exemplo deveria serTable(f, {x, 0, 5})
? Também não entendo o objetivox
, pois apenas aplica a função ao intervalo.Respostas:
Haskell,
muitos bytes anteriores contam127 * 0,9 = 114,3 bytesSem loops, apenas recursão.
#
é o mapa:(*2) # [1,2,3]
->[2,4,6]
&
é ninho:((*2) & 3) 4
->48
i
é aplicável:i (*2) 7
->14
r
é o intervalo:r 4
->[1,2,3,4]
?
é fold:((+) ? 0) [1,2,3,4]
->10
%
é tabela:(*2) % (2,4)
->[4,6,8]
Conforme solicitado, uma versão não-gasta com comentários. Observe
&
e?
são operadores de infixo ternários, que exigem parênteses adicionais quando chamados ou correspondidos por padrão.Obrigado a @dfeuer e @Zgarb por algumas dicas úteis
fonte
m#q=reverse$f((:).m)[]q
,. Este é o mesmo comprimento que o seu, mas muito mais difícil de ler.!
, tornando-a um nome em vez de um operador:i f=f
.Python 2, 305,1 bytes (-10%
376369366349339 bytes)Quando expandido, equivalente a:
Sem loops!
Bem, isso faz muita coisa
eval
e se seu chefe não aguenta loops, ele odeia avaliar. Mas eles terão que aturar issoUma maneira de fazer
range
um lambda é apreciada, para que eu não precise executar nenhuma função (Shudder.).Explicações:
m=lambda f,l:eval("["+"f(l.pop()),"*len(l)+"][::-1]")
n=lambda f,x,l:eval("f("*l+"*x"+")"*l)
r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
eval
editada, retorne[0]
ou use recursão para obter os resultados anteriores e adicione o índice atual à lista. Avalia.a=lambda f,a:eval("f(a["+
r (len (a))[1:-1].replace(",","-1],a[")+"-1])")
a
. Avalia!f=lambda f,x,l:eval("f("*len(l)+"x,["+
r (len (l))[1:-1].replace(",","-1]),l[")+"-1])")
t=lambda f,n,x:eval("[f("+
r (x) [n-1:].replace(",","),f(")[1:-1]+")]")
Mapeie, aninhe, alcance, aplique, dobre, tabela.
Obrigado @Zgarb por um lambda para range!
fonte
r=lambda i:[]if i<1 else r(i-1)+[i]
? Sem loops, apenas recursão.eval
para mostrar-lhes como para loops não são tão ruins :)e=eval
:r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
Javascript ES6, 197 * 0,9 = 177,3 bytes
Mapa (
M=(f,l)=>F((a,b)=>[...a,f(b)],[],l)
):Usa Fold para concaturar os resultados de
f
aplicado a todos os membrosl
em uma lista vazia. O uso de funções integradas reduz o valor paraM=(f,l)=>l.map(f)
(não o utilizou porque parece barato ...?).Ninho (
N=(f,x,n)=>f(--n?N(f,x,n):x)
):Aplique
f
recursivamente atén
diminuir para 0.Aplicar (
A=(f,l)=>f(...l)
):Usa o spread (
...
operador) para aplicarl
paraf
.Intervalo (
R=n=>n--?[...R(n),n+1]:[]
):Concat
n
na chamada recursiva do intervalo até quen
seja diminuído para 0.Dobra (
F=(f,x,l,n=l.length)=>n--?f(F(f,x,l,n),l[n]):x
):Aplica a chamada recursiva de Fold e o
n
'th elemento del
tof
atén
é diminuído para 0. O uso de funções internas reduz isso paraF=(f,x,l)=>l.reduce(f,x)
(novamente, parecia barato ...).Tabela (
T=(f,i)=>([n,x]=i,M(q=>f(q+n-1),R(x-n+1)))
):Inicializa primeiro
n
ex
para o iMin e o iMax usando destructuring ([n,x]=i
), depois usa Range para construir a tabela de valores do iMin ao iMax.f
é então aplicado sobre a tabela usando Map e o resultado é retornado.fonte
Python 3, 218 bytes
A versão ilegível:
A versão (mais) legível:
Indo embora um lambda de cada vez:
Função de mapa
P
P=lambda f,x:[f(_)for _ in x]
Apenas um iterador simples. Não há muito a dizer aqui.
Função Nest
Y
Y=lambda f,x,z:Y(f,f(x),z-1)if z else x
Repetindo até
z
atingir zero, aplicandof
sempre. A cláusula if no final parece desajeitada; talvez haja uma maneira melhor de terminar a recursão.Aplicar função
T
T=lambda f,x:f(*x)
O Python tem um bom operador de expansão para fazer todo o trabalho pesado para mim.
Função de faixa
H
H=lambda f,x=0:(H(f-1)if~-f else[])+[f]
Este foi mais difícil do que eu esperava. Acabou adotando uma abordagem recursiva. Novamente, a construção if-else ocupa muitos bytes e acho que pode ser melhorada. Por que ele tem um boneco
x=0
, você pergunta? É para que quando eu comprimo com oexec
, eu possa substituir em=lambda f,x
vez de apenas=lambda f
.Função de dobra
O
O=lambda f,x,z:O(f,f(x,z[0]),z[1:])if z else x
Muito feliz com este. Apenas corta o primeiro elemento da matriz toda vez que ele se repete, até que não resta mais nada.
Função de tabela
N
N=lambda f,x:(N(f,[x[0],x[1]-1])if x[1]-x[0]else[])+[f(x[1])]
Este é horrível e tenho certeza de que há espaço para melhorias. Tentou usar as funções de alcance e mapa definidas anteriormente para um
map(f,range(x,y))
tipo de construção, mas sem muito sucesso. Acabou fazendo uma terrível abordagem recursiva que compartilha alguma semelhança com a função range.Todas as lambdas são agrupadas em um
exec
com areplace
para diminuir significativamente a contagem de bytes.fonte
[f(_)for _ in x]
poderia ser reduzido paramap(f,x)
, mas depois lembrei-me que o desafio eraJulia, 181 bytes
Nenhum bônus para mim; Eu usei loops liberalmente. Desculpe chefe, mas os loops em Julia são eficientes!
Adicionar as elipses após um argumento a uma função quebra uma matriz, tupla ou o que você coloca nos argumentos da função regular. Caso contrário, a função pensará que você está tentando passar uma matriz (ou tupla, etc.). Não tem efeito para argumentos únicos.
Nomes de funções:
M
N
A
R
F
T
fonte
tinilisp , 325 * 0,9 = 292,5
A linguagem é mais nova que a pergunta, mas não vai ganhar de qualquer maneira.
Define as funções
A
(aplicar),M
(mapa),N
(aninhar),R
(intervalo),T
(tabela) eF
(dobra), juntamente com algumas funções auxiliares.T
espera uma lista de dois números inteiros para seu segundo argumento.Tinylisp nem sequer tem construções de loop; tudo é realizado usando recursão. Várias dessas funções não são recursivas de cauda , portanto, se você as chamar em grandes listas, elas provavelmente explodirão a pilha de chamadas. Todos eles poderiam ser implementados com recursão de cauda ... mas seriam necessários mais bytes, e isso é código de golfe.
Aqui está uma versão expandida com espaço em branco e palavras reais para nomes, que devem ser bem legíveis se você estiver familiarizado com o Lisp. (Alias a maioria dos tinylisp embutidos, exceto
q
(quote) ei
(if).)Mais explicações disponíveis mediante solicitação.
Saída de amostra
Usa o ambiente REPL da minha implementação de referência. Eu usei
q
(quote) para a função unária es
(subtrai) como a função binária desses exemplos, bem como a função@
(definida neste código) que retorna uma lista de seus argumentos.fonte
Python 2.x: 450.6 bytes (493 bytes antes de 10% de desconto)
Resposta golfe:
Esta pergunta foi divertida. Decidi escrever minhas funções sem usar os equivalentes do Python (embora isso possa ter sido uma brecha válida) e escrever as funções como se o Python fosse compatível com a recursão da cauda. Para fazer isso funcionar, usei muitos parâmetros opcionais que permitem que as chamadas necessárias ainda funcionem.
Abaixo, tenho listagens ungolfed para cada função.
Apply
:Map
:Nest
:Observe que essa função requer que o passado
function
seja capaz de representar vários argumentos de maneira variável. Outra abordagem seria impor que a função sempre recebesse uma lista única, mas isso exigiria que as funções passadas pudessem interpretar listas de argumentos. Havia suposições de qualquer maneira, então eu escolhi a que se encaixava melhor no resto do sistema.Range
:Fold
:Table
:Aqui está um exemplo de saída usando as seguintes funções auxiliares:
fonte
Ceilão,
370 * 0,9 = 333364 * 0,9 = 327,4A maioria dessas funções já está disponível no pacote de idiomas do Ceilão (embora às vezes com uma assinatura um pouco diferente), mas as definimos aqui como solicitado na pergunta.
Na verdade, apenas duas das funções (
t
ef
) estão realmente usando recursão (sobre listas e números inteiros, respectivamente), as outras são baseadas nelas. (O aplicativo é um pouco estranho, realmente não se relaciona com os outros.)Interpreto "List" como o tipo Sequencial do Ceilão, que é uma sequência imutável de elementos (possivelmente vazios).
[R*]
significaSequential<R>
- por alguma razão, também podemos escrevê-loR[]
, que é um byte mais curto.Um tipo de função é
Callable<R, A>
, ondeA
é um tipo de tupla para os argumentos, como[X, Y, Z]
(por exemplo, algum subtipo deAnything[]
). Como atalho, podemos escrever emR(X,Y,Z)
vez deCallable<R,[X,Y,Z]>
.Eu alias
Integer
comoI
salvar alguns bytes.Aqui está uma versão formatada (e ligeiramente comentada):
Usando "loops"
Tabela e Mapa podem ser implementados mais curtos usando loops (na verdade, uma compreensão de sequência):
Embora eu não tenha certeza se o uso do
..
operador para o intervalo inteiro conta como usando uma função interna. Se isso for permitido, o código resultante é este aqui, comprimento 312:(Pode ser ainda mais curto definindo
r(I i) => 1..i
, resultando na pontuação 301. Embora isso pareça ainda mais trapaça.)Se
..
não for permitido, teremos que implementá-lo novamente. Podemos usar essas implementações parar
et
(com om
acima):Isso resulta em 348 bytes, melhor que a versão completamente recursiva, mas não após a aplicação do bônus.
fonte
Groovy (146 bytes) (146 * 90% = 131,4)
PS: Eu não sei o que você está considerando como um 'loop' nesse contexto, só apliquei o bônus depois que me disseram nos comentários pelo OP e removerei se 2-3 usuários adicionais disserem que essas funções de coleção e iteradores são loops e que eu não mereço o bônus. Além disso, se você quiser me chamar para usar 1..it, faça-o e eu o retrabalharei / atualizo meu número de bytes.
Exemplo de entrada / saída
Saída
Experimente você mesmo: https://groovyconsole.appspot.com/edit/5203951758606336
fonte