Votre entreprise ne fait que commencer un projet, et pour la première fois vous avez décidé d'utiliser un style de code de programmation fonctionnel. Cependant, votre patron est vraiment méfiant et ne veut pas utiliser les fonctions intégrées, et vous oblige à implémenter vous-même les fonctions principales. En particulier , vous devez écrire les fonctions: Map
, Nest
, Apply
, Range
, Fold
et Table
dans une langue de votre choix. Le patron est un homme très occupé, et il veut que les programmes soient aussi courts que possible, donc il ne perd pas de temps à lire. Il aimerait également que vous n'utilisiez pas de boucles, donc vous aurez une réduction de 10% sur le nombre d'octets pour ne pas utiliser de boucles.
Les exigences détaillées des fonctions sont ci-dessous:
Carte
La Map
fonction prend deux paramètres: f
et list
où f
est une fonction et list
est une liste de valeurs. Il doit renvoyer l' f
appliqué à chaque élément de list
. Par conséquent, cela fonctionnera comme tel:
Map(f,{a,b,c})
Retour
{ f(a), f(b), f(c) }
et
Map(f, {{a,b},{b,c}})
Retour
{ f({a,b}), f({b,c})}
Nid
La Nest
fonction prend trois paramètres ainsi: f
, arg
, times
où f
est une fonction, arg
est son argument de départ, et times
est combien de fois la fonction est appliquée. Il doit renvoyer une expression avec f
des times
temps appliqués à arg
. Par conséquent, cela fonctionnera comme tel:
Nest(f, x, 3)
Retour
f(f(f(x)))
et
Nest(f, {a,b}, 3)
Retour
f(f(f({a,b})))
Appliquer
La Apply
fonction prend deux paramètres: f
et args
où f
est une fonction et args
une liste. Il devrait s'appliquer f
au args
. Donc:
Apply(f, {a,b,c})
Retour
f(a,b,c)
Gamme
La Range
fonction prend un entier r
et génère les nombres entiers jusqu'à ce nombre. Donc:
Range(5)
Retour
{ 1, 2, 3, 4, 5}
Plier
La Fold
fonction prend trois paramètres f
, arg
, others
où f
est une fonction, arg
est simple paramètre, et others
une liste. Cela fonctionnera comme tel:
Fold(f, x, {a, b, c, d})
Retour
f(f(f(f(x,a),b),c),d)
Table
Les fonctions de table doivent prendre une fonction f
et un paramètre appelé iterator
sous la forme: {iMin, iMax}
où iMin
et iMax
sont des entiers. Vous devez appliquer f
sur la plage spécifiée. Donc:
Table(f, {0, 5})
Retour
{f(0), f(1), f(2), f(3), f(4), f(5)}
J'ai utilisé la définition de ces fonctions à partir de la page de programmation fonctionnelle de Mathematica , alors allez-y si vous avez besoin de plus d'informations. Notez que vous n'aurez pas besoin d'implémenter toutes les versions des fonctions présentées dans cette page, mais seulement celles écrites dans ce post.
Les échappatoires standard sont interdites comme d'habitude.
Dans le cas où votre langage ne permet pas de passer des fonctions comme arguments, vous devez implémenter cette fonctionnalité et l'ajouter à votre réponse. Cependant, le nombre d'octets de cette opération ne sera pas ajouté au total.
C'est le golf de code donc le code le plus court gagne. Bonne chance!!!
la source
Table
fonctionne ici. Votre exemple est-il censé êtreTable(f, {x, 0, 5})
? Je ne comprends pas du tout le butx
, car il applique simplement la fonction à la plage.Réponses:
Haskell, de
nombreux octets précédents comptent127 * 0,9 = 114,3 octetsPas de boucles, juste une récursivité.
#
est la carte:(*2) # [1,2,3]
->[2,4,6]
&
est nid:((*2) & 3) 4
->48
i
est appliquer:i (*2) 7
->14
r
est gamme:r 4
->[1,2,3,4]
?
est plié:((+) ? 0) [1,2,3,4]
->10
%
est la table:(*2) % (2,4)
->[4,6,8]
Comme demandé une version non golfée avec commentaires. Remarquez,
&
et ce?
sont des opérateurs d'infixe ternaire, qui nécessitent des parenthèses supplémentaires lorsqu'ils sont appelés ou que le modèle correspond.Merci à @dfeuer et @Zgarb pour quelques conseils utiles
la source
m#q=reverse$f((:).m)[]q
. C'est la même longueur que la vôtre, mais beaucoup plus difficile à lire.!
en faisant un nom au lieu d'un opérateur:i f=f
.Python 2, 305.1 octets (-10%
376369366349339 octets)Une fois développé, équivalent à:
Pas de boucles!
Eh bien, cela fait beaucoup de travail
eval
et si votre patron ne supporte pas les boucles, alors il déteste l'évaluation. Mais ils vont devoir le supporterUne façon de faire
range
dans un lambda est appréciée donc je n'ai pas à faire de fonctions (Shudder.).Explications:
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
éditée, renvoie[0]
ou utilise la récursivité pour obtenir les résultats précédents et ajoute l'index en cours à la liste. Evals it.a=lambda f,a:eval("f(a["+
r (len (a))[1:-1].replace(",","-1],a[")+"-1])")
a
. Evals it!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]+")]")
Carte, nid, plage, application, pli, table.
Merci @Zgarb pour un lambda pour la portée!
la source
r=lambda i:[]if i<1 else r(i-1)+[i]
? Pas de boucles, seulement récursivité.eval
pour leur montrer comment les boucles ne sont pas si mauvaises :)e=eval
:r=lambda i:e("r(i-1)+"*(i>1)+"[i]")
Javascript ES6, 197 * 0,9 = 177,3 octets
Carte (
M=(f,l)=>F((a,b)=>[...a,f(b)],[],l)
):Utilise Fold pour concaténer les résultats de
f
appliqué à chaque membre del
sur une liste vide. L'utilisation de fonctions intégrées réduit ce paramètre àM=(f,l)=>l.map(f)
(ne l'a pas utilisé car il semble bon marché ...?).Nest (
N=(f,x,n)=>f(--n?N(f,x,n):x)
):Appliquer
f
récursivement jusqu'à ce qu'iln
soit décrémenté à 0.Appliquer (
A=(f,l)=>f(...l)
):Utilise la propagation (
...
opérateur) à appliquerl
surf
.Plage (
R=n=>n--?[...R(n),n+1]:[]
):Concat
n
à l'appel récursif de Range jusqu'à ce qu'iln
soit décrémenté à 0.Pli (
F=(f,x,l,n=l.length)=>n--?f(F(f,x,l,n),l[n]):x
):Applique l'appel récursif de Fold et l'
n
élément 'th del
tof
jusqu'àn
est décrémenté à 0. L'utilisation de fonctions intégrées réduit cela àF=(f,x,l)=>l.reduce(f,x)
(encore une fois, semblait bon marché ...).Tableau (
T=(f,i)=>([n,x]=i,M(q=>f(q+n-1),R(x-n+1)))
):Initialise d'abord
n
etx
à iMin et iMax en utilisant destructuring ([n,x]=i
), puis utilise Range pour construire la table de valeurs d'iMin à iMax.f
est ensuite appliqué sur la table à l'aide de Map et le résultat est renvoyé.la source
Python 3, 218 octets
La version illisible:
La version (plus) lisible:
En y allant un lambda à la fois:
Fonction carte
P
P=lambda f,x:[f(_)for _ in x]
Un simple itérateur. Pas grand chose à dire ici.
Fonction Nest
Y
Y=lambda f,x,z:Y(f,f(x),z-1)if z else x
Récursif jusqu'à ce qu'il atteigne
z
zéro, s'appliquant àf
chaque fois. La clause if à la fin semble maladroite; il y a peut-être une meilleure façon de mettre fin à la récursivité.Appliquer la fonction
T
T=lambda f,x:f(*x)
Python a un bon opérateur d'expansion pour faire tout le gros du travail pour moi.
Fonction de gamme
H
H=lambda f,x=0:(H(f-1)if~-f else[])+[f]
Celui-ci était plus difficile que ce à quoi je m'attendais. A fini par adopter une approche récursive. Encore une fois, la construction if-else prend beaucoup d'octets, et je pense qu'elle peut être améliorée. Pourquoi at-il un mannequin
x=0
, demandez-vous? C'est pour que lorsque je le comprime avec leexec
, je puisse le remplacer=lambda f,x
au lieu de juste=lambda f
.Fonction de pliage
O
O=lambda f,x,z:O(f,f(x,z[0]),z[1:])if z else x
Assez content avec celui-ci. Élimine simplement le premier élément du tableau à chaque fois qu'il revient, jusqu'à ce qu'il ne reste plus rien.
Fonction de table
N
N=lambda f,x:(N(f,[x[0],x[1]-1])if x[1]-x[0]else[])+[f(x[1])]
Celui-ci est horrible et je suis sûr qu'il y a place à amélioration. J'ai essayé d'utiliser les fonctions de plage et de carte précédemment définies pour une
map(f,range(x,y))
sorte de construction, mais sans grand succès. J'ai fini par faire une terrible approche récursive qui partage une certaine similitude avec la fonction de plage.Tous les lambdas sont enveloppés dans un
exec
avec unreplace
pour raccourcir considérablement le nombre d'octets.la source
[f(_)for _ in x]
pourrait être raccourcimap(f,x)
, mais je me suis alors souvenu du défiJulia, 181 octets
Pas de bonus pour moi; J'ai utilisé des boucles généreusement. Désolé patron, mais les boucles de Julia sont efficaces!
L'ajout d'ellipses après un argument à une fonction casse un tableau, un tuple ou ce que vous avez en arguments de fonction réguliers. Sinon, la fonction pensera que vous essayez de passer un tableau (ou un tuple, etc.). Il n'a aucun effet pour les arguments uniques.
Noms des fonctions:
M
N
A
R
F
T
la source
tinylisp , 325 * 0,9 = 292,5
La langue est plus récente que la question, mais elle ne gagnera pas de toute façon.
Définit les fonctions
A
(appliquer),M
(carte),N
(imbriquer),R
(plage),T
(table) etF
(replier), ainsi que quelques fonctions d'assistance.T
attend une liste de deux entiers pour son deuxième argument.Tinylisp n'a même aucune construction de boucle; tout est accompli en utilisant la récursivité. Plusieurs de ces fonctions ne sont pas récursives , donc si vous les appelez sur de grandes listes, elles feront probablement exploser la pile d'appels. Ils pourraient tous être implémentés avec une récursivité de queue ... mais cela prendrait plus d'octets, et c'est le code golf.
Voici une version étendue avec des espaces et de vrais mots pour les noms, qui devraient être assez lisibles si vous êtes familier avec Lisp. (J'ai alias la plupart des commandes internes de tinylisp à l'exception de
q
(citation) eti
(si).)Plus d'explications disponibles sur demande.
Exemple de sortie
Utilise l'environnement REPL de mon implémentation de référence. J'ai utilisé
q
(quote) pour la fonction unaire ets
(soustraire) comme fonction binaire pour ces exemples, ainsi que la fonction@
(définie dans ce code) qui renvoie une liste de ses arguments.la source
Python 2.x: 450,6 octets (493 octets avant 10% de réduction)
Réponse golfée:
Cette question était amusante. J'ai décidé d'écrire mes fonctions sans utiliser les équivalents Python (bien que cela ait pu être une faille valide) et d'écrire les fonctions comme si Python supporte la récursivité de la queue. Pour que cela fonctionne, j'ai utilisé de nombreux paramètres facultatifs qui permettent aux appels requis de continuer à fonctionner.
Ci-dessous, j'ai des listes non golfées pour chaque fonction.
Apply
:Map
:Nest
:Notez que cette fonction nécessite que le passé
function
puisse représenter plusieurs arguments de manière variable. Une autre approche aurait consisté à faire en sorte que la fonction reçoive toujours une seule liste, mais cela aurait nécessité que les fonctions passées soient capables d'interpréter des listes d'arguments. Il y avait des hypothèses de toute façon, alors j'ai choisi celle qui convenait mieux au reste du système.Range
:Fold
:Table
:Voici un exemple de sortie utilisant les fonctions d'assistance suivantes:
la source
Ceylan,
370 * 0,9 = 333364 * 0,9 = 327,4La plupart de ces fonctions sont déjà disponibles dans le package de langue de Ceylan (bien que parfois avec une signature un peu différente), mais nous les définissons ici comme demandé dans la question.
En fait, seules deux des fonctions (
t
etf
) utilisent réellement la récursivité (sur des listes et des entiers, respectivement), les autres sont basées sur celles-ci. (Appliquer est un peu aberrant, il n'a pas vraiment de rapport avec les autres.)J'interprète "List" comme le type séquentiel de Ceylan, qui est une séquence d'éléments ordonnée (éventuellement vide) immuable.
[R*]
signifieSequential<R>
- pour une raison quelconque, nous pouvons également l'écrireR[]
, qui est un octet plus court.Un type de fonction est
Callable<R, A>
, oùA
est un type de tuple pour les arguments, comme[X, Y, Z]
(c'est-à-dire un sous-type deAnything[]
). Comme raccourci, nous pouvons écrire à laR(X,Y,Z)
place deCallable<R,[X,Y,Z]>
.J'Aliased
Integer
queI
de sauver quelques octets.Voici une version formatée (et légèrement commentée):
Utilisation de "boucles"
Table et Map peuvent être implémentés plus rapidement en utilisant des boucles (en fait, une compréhension de séquence):
Bien que je ne sais pas si l'utilisation de l'
..
opérateur pour la plage d'entiers compte comme une fonction intégrée. Si cela est autorisé, le code résultant est le suivant, longueur 312:(Il pourrait être encore plus court en le définissant
r(I i) => 1..i
, ce qui donnerait le score 301. Bien que cela ressemble encore plus à de la triche.)Si
..
n'est pas autorisé, nous devrons l'implémenter à nouveau. Nous pouvons utiliser ces implémentations pourr
ett
(avec ce quim
précède):Cela donne 348 octets, mieux que la version complètement récursive, mais pas après avoir appliqué le bonus.
la source
Groovy (146 octets) (146 * 90% = 131,4)
PS Je ne sais pas ce que vous considérez comme une `` boucle '' dans ce contexte, je n'ai appliqué le bonus qu'après avoir été informé dans les commentaires par OP et je supprimerai si 2-3 utilisateurs supplémentaires disent ces fonctions de collecte et itérateurs sont des boucles et que je ne mérite pas le bonus. De plus, si vous voulez m'appeler sur mon utilisation de 1..it, faites-le et je vais le retravailler / mettre à jour mon bytecount.
Exemple d'entrée / sortie
Production
Essayez-le vous-même: https://groovyconsole.appspot.com/edit/5203951758606336
la source