Mathematica, 100%, 141 octets
f@x_:=Count[1>0]@Table[ImageInstanceQ[x,"caprine animal",RecognitionThreshold->i/100],{i,0,50}];If[f@#>f@ImageReflect@#,"Up","Down"]<>"goat"&
Eh bien, cela ressemble plus à de la triche. C'est aussi incroyablement lent et très bête. Function f
voit à peu près à quelle hauteur vous pouvez définir le seuil de reconnaissance dans l’un des systèmes intégrés de vision par ordinateur de Mathematica tout en reconnaissant l’image comme un animal caprin.
Nous voyons alors si l'image ou l'image retournée est plus boueuse. Ne fonctionne que sur l’image de votre profil car l’égalité est brisée au profit de downgoat. Il y a probablement beaucoup de façons d'améliorer cela, notamment de lui demander si l'image représente des bovidés ou d'autres généralisations du type d'entité Caprine.
La réponse sous forme écrite marque 100% pour le premier ensemble de tests et 94% pour le second ensemble de tests, car l'algorithme donne un résultat non concluant pour la chèvre 1. Ce résultat peut être remonté à 100% au prix d'un temps de calcul encore plus long. tester plus de valeurs de RecognitionThreshold
. Ressuscitant 100
à 1000
sufficies; Pour une raison quelconque, Mathematica pense que c'est une image très inconsistante! Changer l'entité de reconnaissance d'un animal caprin à un mammifère sabot semble également fonctionner.
Ungolfed:
goatness[image_] := Count[
Table[
ImageInstanceQ[
image, Entity["Concept", "CaprineAnimal::4p79r"],
RecognitionThreshold -> threshold
],
{threshold, 0, 0.5, 0.01}
],
True
]
Function[{image},
StringJoin[
If[goatness[image] > goatness[ImageReflect[image]],
"Up",
"Down"
],
"goat"
]
]
Solution alternative, bonus de 100% +
g[t_][i_] := ImageInstanceQ[i, "caprine animal", RecognitionThreshold -> t]
f[i_, l_: 0, u_: 1] := Module[{m = (2 l + u)/3, r},
r = g[m] /@ {i, ImageReflect@i};
If[Equal @@ r,
If[First@r, f[i, m, u], f[i, l, m]],
If[First@r, "Up", "Down"] <> "goat"
]
]
Celui-ci utilise la même stratégie qu'auparavant, mais avec une recherche binaire au dessus du seuil. Il y a deux fonctions impliquées ici:
g[t]
retourne si son argument est une image de chèvre avec seuil t
.
f
prend trois paramètres: une image et une limite supérieure et inférieure sur le seuil. C'est récursif; cela fonctionne en testant un seuil m
entre les seuils haut et bas (biaisé vers le bas). Si l'image et l'image réfléchie sont toutes deux bougeuses ou non, cela élimine la partie inférieure ou supérieure de la plage, selon le cas, et se rappelle. Sinon, si une image est chèvre et que l'autre n'est pas chèvre, elle est retournée Upgoat
si la première image est chèvre et Downgoat
sinon (si la seconde, l'image réfléchie est chèvre).
Les définitions de fonctions méritent une petite explication. Tout d'abord, l'application de la fonction est associative à gauche. Cela signifie que quelque chose comme g[x][y]
est interprété comme (g[x])[y]
; "le résultat de g[x]
appliqué à y
."
Deuxièmement, l'attribution dans Mathematica équivaut à peu près à définir une règle de remplacement. Autrement dit, f[x_] := x^2
ne signifie pas "déclarer une fonction nommée f
avec le paramètre x
qui retourne x^2
;" sa signification est plus proche de, "chaque fois que vous voyez quelque chose comme f[ ... ]
, appelez la chose à l'intérieur x
et remplacez la chose entière par x^2
".
En réunissant ces deux éléments, nous pouvons voir que la définition de g
indique à Mathematica de remplacer toute expression de la forme (g[ ... ])[ ... ]
par la partie droite de la tâche.
Lorsque Mathematica rencontre l'expression g[m]
(dans la deuxième ligne de f
), il voit que l'expression ne correspond à aucune règle connue et la laisse inchangée. Ensuite, il correspond à l' Map
opérateur /@
, dont les arguments sont g[m]
et à la liste {i, ImageReflect@i}
. ( /@
est une notation infixe; cette expression est exactement équivalente à Map[g[m], { ... }]
.) Le Map
est remplacé par l'application de son premier argument à chaque élément de son second argument, nous obtenons donc {(g[m])[i], (g[m])[ ... ]}
. Mathematica voit maintenant que chaque élément correspond à la définition de g
et effectue le remplacement.
De cette manière, nous devons g
agir comme une fonction qui renvoie une autre fonction. c'est-à-dire qu'il agit à peu près comme nous l'avons écrit:
g[t_] := Function[{i}, ImageInstanceQ[i, "caprine animal", RecognitionThreshold -> t]]
(Sauf dans ce cas, cela g[t]
équivaut à un Function
, alors qu'avant g[t]
, il n'était pas transformé du tout.)
Le dernier tour que j'utilise est un motif optionnel. Le modèle l_ : 0
signifie "correspond à n'importe quelle expression et le rend disponible en tant que l
, ou ne correspond à rien et le rend 0
disponible l
". Donc, si vous appelez f[i]
avec un seul argument (l’image à tester), c’est comme si vous aviez appelé f[i, 0, 1]
.
Voici le harnais de test que j'ai utilisé:
gist = Import["https://api.github.com/gists/3fb94bfaa7364ccdd8e2", "JSON"];
{names, urls} = Transpose[{"filename", "raw_url"} /. Last /@ ("files" /. gist)];
images = Import /@ urls;
result = f /@ images
Tally@MapThread[StringContainsQ[##, IgnoreCase -> True] &, {names, result}]
(* {{True, 18}} *)
user = "items" /.
Import["https://api.stackexchange.com/2.2/users/40695?site=codegolf", "JSON"];
pic = Import[First["profile_image" /. user]];
name = First["display_name" /. user];
name == f@pic
(* True *)