Mathematica, 100%, 141 bytes
f@x_:=Count[1>0]@Table[ImageInstanceQ[x,"caprine animal",RecognitionThreshold->i/100],{i,0,50}];If[f@#>f@ImageReflect@#,"Up","Down"]<>"goat"&
Bueno, esto se siente más que un poco como hacer trampa. También es increíblemente lento, además de ser muy tonto. La función f
ve aproximadamente qué tan alto puede establecer el umbral de Reconocimiento en una de las funciones de visión por computadora de Mathematica, y aún así reconocer la imagen como un animal Caprino.
Luego vemos si la imagen o la imagen volteada es más caprichosa. Funciona en su imagen de perfil solo porque el empate está roto a favor de downgoat. Probablemente hay muchas formas en que esto podría mejorarse, incluida la pregunta si la imagen representa Bovids u otras generalizaciones del tipo de entidad animal Caprino.
Responda como puntajes escritos 100% para el primer conjunto de pruebas y 94% para el segundo conjunto de pruebas, ya que el algoritmo arroja un resultado no concluyente para la cabra 1. Esto puede elevarse hasta el 100% a expensas de un tiempo de cálculo aún más largo probando más valores de RecognitionThreshold
. Subiendo de 100
a 1000
suficientes; ¡Por alguna razón, Mathematica piensa que es una imagen muy desagradable! Cambiar la entidad de reconocimiento de Caprine animal a Hoofed Mammal también parece funcionar.
Sin golf:
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"
]
]
Solución alternativa, 100% + bonificación
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"
]
]
Éste usa la misma estrategia que antes, pero con una búsqueda binaria por encima del umbral. Aquí hay dos funciones involucradas:
g[t]
devuelve si su argumento es o no una imagen caprichosa con umbral t
.
f
toma tres parámetros: una imagen y un límite superior e inferior en el umbral. Es recursivo; funciona probando un umbral m
entre los umbrales superior e inferior (sesgado hacia el inferior). Si la imagen y la imagen reflejada son caprichosas o no caprichosas, elimina la parte inferior o superior del rango según corresponda y se llama a sí misma nuevamente. De lo contrario, si una imagen es caprichosa y la otra no es caprichosa, regresa Upgoat
si la primera imagen es caprichosa y de lo Downgoat
contrario (si la segunda imagen reflejada es caprichosa).
Las definiciones de funciones merecen una pequeña explicación. Primero, la aplicación de la función es asociativa a la izquierda. Esto significa que algo así g[x][y]
se interpreta como (g[x])[y]
; "el resultado de g[x]
aplicado a y
".
Segundo, la asignación en Mathematica es más o menos equivalente a definir una regla de reemplazo. Es decir, f[x_] := x^2
no , no significa "declarar una función llamada f
con el parámetro x
que devuelve x^2
;" su significado está más cerca de "cuando veas algo así f[ ... ]
, llama a la cosa que está adentro x
y reemplaza todo con x^2
".
Al poner estos dos juntos, podemos ver que la definición de g
es decirle a Mathematica que reemplace cualquier expresión de la forma (g[ ... ])[ ... ]
con el lado derecho de la tarea.
Cuando Mathematica encuentra la expresión g[m]
(en la segunda línea de f
), ve que la expresión no coincide con ninguna regla que conozca y la deja sin cambios. Luego coincide con el Map
operador /@
, cuyos argumentos son g[m]
y la lista {i, ImageReflect@i}
. ( /@
es notación infija; esta expresión es exactamente equivalente a Map[g[m], { ... }]
). El Map
se reemplaza aplicando su primer argumento a cada elemento de su segundo argumento, por lo que obtenemos {(g[m])[i], (g[m])[ ... ]}
. Ahora Mathematica ve que cada elemento coincide con la definición de g
y hace el reemplazo.
De esta manera, tenemos g
que actuar como una función que devuelve otra función; es decir, actúa más o menos como escribimos:
g[t_] := Function[{i}, ImageInstanceQ[i, "caprine animal", RecognitionThreshold -> t]]
(Excepto en este caso g[t]
por sí solo se evalúa como a Function
, mientras que antes g[t]
solo no se transformó en absoluto).
El truco final que uso es un patrón opcional. El patrón l_ : 0
significa "hacer coincidir cualquier expresión y hacer que esté disponible como l
, o no hacer coincidir nada y hacer que 0
esté disponible como l
". Entonces, si llamas f[i]
con un argumento (la imagen a probar) es como si hubieras llamado f[i, 0, 1]
.
Aquí está el arnés de prueba que utilicé:
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 *)