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"&
Bem, isso parece mais do que um pouco como trapaça. Também é incrivelmente lento, além de ser muito bobo. A função f
vê aproximadamente o quão alto você pode definir o limite de reconhecimento em um dos recursos integrados de visão computacional do Mathematica e ainda reconhece a imagem como um animal caprino.
Depois, vemos se a imagem ou a imagem invertida é mais caprichosa. Funciona na sua imagem de perfil apenas porque o empate está quebrado em favor do downgoat. Provavelmente, existem várias maneiras de melhorar isso, incluindo perguntar se a imagem representa os bovinos ou outras generalizações do tipo de entidade animal caprina.
Responda como escores escritos 100% para o primeiro conjunto de testes e 94% para o segundo conjunto de testes, pois o algoritmo produz um resultado inconclusivo para a cabra 1. Isso pode ser aumentado de volta para 100% às custas de um tempo computacional ainda mais longo. testando mais valores de RecognitionThreshold
. Aumentar de 100
para 1000
suficiências; por alguma razão, o Mathematica acha que essa é uma imagem muito desagradável! Mudar a entidade de reconhecimento de Caprino para Hoofed Mammal também parece funcionar.
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"
]
]
Solução alternativa, 100% + bônus
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"
]
]
Este usa a mesma estratégia de antes, mas com uma pesquisa binária acima do limite. Há duas funções envolvidas aqui:
g[t]
retorna se seu argumento é ou não uma imagem de cabra com limite t
.
f
usa três parâmetros: uma imagem e um limite superior e inferior no limite. É recursivo; funciona testando um limite m
entre os limites superior e inferior (inclinado para o inferior). Se a imagem e a imagem refletida forem de cabra ou não de cabra, ela eliminará a parte inferior ou superior do intervalo conforme apropriado e se chamará novamente. Caso contrário, se uma imagem for de cabra e a outra não de cabra, ela retornará Upgoat
se a primeira imagem for de cabra e Downgoat
caso contrário (se a segunda imagem refletida for de cabra).
As definições de função merecem uma pequena explicação. Primeiro, a aplicação da função é associativa à esquerda. Isso significa que algo como g[x][y]
é interpretado como (g[x])[y]
; "o resultado de g[x]
aplicado a y
."
Segundo, a atribuição no Mathematica é aproximadamente equivalente à definição de uma regra de substituição. Isto é, f[x_] := x^2
se não significa "declarar uma função chamada f
com o parâmetro x
que retorna x^2
"; seu significado está mais próximo de "sempre que vir algo assim f[ ... ]
, chame a coisa por dentro x
e substitua por tudo x^2
".
Juntando esses dois, podemos ver que a definição de g
está dizendo ao Mathematica para substituir qualquer expressão do formulário (g[ ... ])[ ... ]
pelo lado direito da tarefa.
Quando o Mathematica encontra a expressão g[m]
(na segunda linha de f
), vê que a expressão não corresponde a nenhuma regra que conhece e a deixa inalterada. Em seguida, ele corresponde ao Map
operador /@
, cujos argumentos são g[m]
e a lista {i, ImageReflect@i}
. ( /@
é uma notação infix; essa expressão é exatamente equivalente a Map[g[m], { ... }]
.) A Map
é substituída pela aplicação de seu primeiro argumento a cada elemento do seu segundo argumento, então obtemos {(g[m])[i], (g[m])[ ... ]}
. Agora, o Mathematica vê que cada elemento corresponde à definição g
e substitui.
Dessa maneira, conseguimos g
agir como uma função que retorna outra função; isto é, age aproximadamente como escrevemos:
g[t_] := Function[{i}, ImageInstanceQ[i, "caprine animal", RecognitionThreshold -> t]]
(Exceto neste caso, g[t]
por si só, avalia como a Function
, enquanto antes g[t]
por si só não foi transformado.)
O truque final que eu uso é um padrão opcional. O padrão l_ : 0
significa "corresponder a qualquer expressão e disponibilizá-lo como l
, ou não corresponder a nada e 0
disponibilizar como l
". Portanto, se você chamar f[i]
com um argumento (a imagem a ser testada), é como se você tivesse chamado f[i, 0, 1]
.
Aqui está o equipamento de teste que eu usei:
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 *)