Quem é esse polígono?

14

Uma maneira conveniente e útil de representar superfícies topológicas é com um polígono fundamental . Cada lado de um polígono corresponde a outro lado e pode ser paralelo ou anti-paralelo. Por exemplo, o aqui é o polígono fundamental de um toro :

Toro

Para descobrir por que esse é um toro, poderíamos imaginar nosso polígono sendo uma folha de papel. Para criar a superfície adequada, queremos dobrar o papel para que as bordas correspondentes se alinhem com as setas seguindo o mesmo caminho. Para o nosso exemplo de toro, podemos começar enrolando o papel em um cilindro para que as duas bordas azuis (rotuladas b) sejam conectadas. Agora pegamos nosso tubo e dobramos para que as duas bordas vermelhas (rotuladas a) se conectem. Deveríamos ter uma forma de rosca, também chamada de toro.

Isso pode ficar um pouco mais complicado. Se você tentar fazer o mesmo com o polígono a seguir, onde uma das arestas está indo na direção oposta:

Klein Bottle

você pode encontrar-se em algum problema. Isso ocorre porque esse polígono representa a garrafa Klein que não pode ser incorporada em três dimensões. Aqui está um diagrama da wikipedia mostrando como você pode dobrar esse polígono em uma garrafa de Klein:

Dobrando uma garrafa de Klein


Como você deve ter adivinhado, a tarefa aqui é pegar um polígono fundamental e determinar qual é a superfície. Para polígonos de quatro lados (as únicas superfícies que você precisará manusear), existem 4 superfícies diferentes.

Eles são

  • Toro

  • Klein Bottle

  • Esfera

  • Plano projetivo

Agora, como este não é o , não espero que você tire uma imagem como entrada. Em vez disso, usaremos uma notação conveniente para representar o polígono fundamental. Você deve ter notado nos dois exemplos acima que eu nomeei as arestas correspondentes com a mesma letra (a ou b), e que dei à borda torcida uma marca adicional para mostrar sua torção. Se começarmos pela borda superior e escrevermos o rótulo de cada borda à medida que avançamos no sentido horário, podemos obter uma notação que representa cada polígono fundamental.

Por exemplo, o Torus fornecido se tornaria abab e a Garrafa Klein se tornaria ab - ab . Para o nosso desafio, vamos torná-lo ainda mais simples. Em vez de marcar as bordas retorcidas com um negativo, em vez disso, tornaremos essas letras maiúsculas.

Tarefa

Dada uma sequência, determine se ela representa um polígono fundamental e gera um valor correspondente à superfície adequada. Você não precisa nomear as superfícies exatamente, você só precisa de 4 valores distintos de saída, cada um representando uma das 4 superfícies com um quinto valor representando entrada incorreta. Todos os casos básicos são abordados na seção Testes simples , todos os carros serão isomórficos para um dos ou inválidos.

Regras

  • Os lados nem sempre serão rotulados com aeb, mas sempre com letras.

  • A entrada válida será composta por 4 letras, duas de um tipo e duas de outro. Você sempre deve produzir a superfície correta para entrada válida.

  • Você deve rejeitar (não gerar nenhum dos 4 valores que representam superfícies) a entrada inválida. Você pode fazer qualquer coisa ao rejeitar uma entrada, desde que seja distinguível das 4 superfícies

  • Isso é portanto, o objetivo é minimizar o número de bytes no seu código-fonte.

Testes

Testes simples

abab Torus
abAb Klein Bottle
abaB Klein Bottle
abAB Projective Plane
aabb Klein Bottle
aAbb Projective Plane
aabB Projective Plane
aAbB Sphere
abba Klein Bottle
abBa Projective Plane
abbA Projective Plane
abBA Sphere

Testes mais complicados

ABAB  Torus
acAc  Klein Bottle
Emme  Projective Plane
zxXZ  Sphere
aaab  Bad input
abca  Bad input
abbaa Bad input
ab1a  Bad input
Post Rock Garf Hunter
fonte
Por que ababum toro e aabbuma garrafa de Klein?
Neil
@ Neil ababé o exemplo no primeiro parágrafo, você pode procurar uma explicação aqui. Aqui está uma imagem mostrando por que aabbé o mesmo abAbque uma garrafa de Klein.
Post Rock Garf Hunter
1
Quais insumos ruins temos para lidar e identificar como ruins? Todas as cordas possíveis? ASCII imprimível? Algum limite de comprimento? Se escrevermos uma função, ela pode ser passada para um objeto não-string? Realmente, todo esse negócio de processamento de insumos me parece um desafio camaleão.
Xnor 21/05
1
@WheatWizard Nesse caso, você pode deixar isso claro no título e no corpo? Ele lê matemática até as Regras, e mesmo lá é fácil perder o requisito de mudança de jogo para validar, em vez de apenas classificá-lo.
Xnor
2
Separadamente, acho que falta uma explicação sobre o que faz uma string ser classificada em uma determinada categoria, pois parece que você não espera que as pessoas façam as contas por trás da classificação. Eu acho que poderia decifrar as regras dos casos de teste, mas isso está longe de ser o ideal.
Xnor 21/05

Respostas:

6

Retina , 123 bytes

i`(.)(\1..)
$2$1
iG`^([a-z])(?!\1)([a-z])(\1\2|\2\1)$
(..)\1
T
.*(.).\1.*|(.)(.)\3\2
B
(.)..\1|.(.)\2.
P
i`(.)..\1
S
....
P

Experimente online! Agradeço a JonathanAllen por apontar um erro no meu código e também como salvar alguns bytes; Eu também joguei mais alguns bytes, então não posso dar crédito a ele por uma figura específica. Explicação:

i`(.)(\1..)
$2$1

Se as duas primeiras letras forem iguais (ignorar maiúsculas e minúsculas), mova a primeira para a quarta. Isso reduz o número de casos que eu preciso testar.

iG`^([a-z])(?!\1)([a-z])(\1\2|\2\1)$

Se não houver exatamente quatro letras, ou as duas primeiras forem iguais, ou as duas últimas não duplicarem as duas primeiras, exclua tudo.

(..)\1
T

O toro é o caso mais fácil: um par de letras, maiúsculas e minúsculas.

.*(.).\1.*|(.)(.)\3\2
B

Se um dos pares corresponder a maiúsculas e minúsculas (nesse caso, outro do par deve corresponder a maiúsculas e minúsculas), esse é um frasco de Klein. Como alternativa, se o par coincidir com maiúsculas e minúsculas, mas for revertido, também será uma garrafa de Klein.

(.)..\1|.(.)\2.
P

Se, por outro lado, o par estiver invertido, mas apenas um dos pares corresponder ao caso, então esse é um plano projetivo.

i`(.)..\1
S

E se o par estiver invertido, mas nenhum deles corresponder ao caso, então essa é uma esfera. ( i`.(.)\1.também funcionaria.)

....
P

Tudo o resto é um plano projetivo.

Neil
fonte
1
@ JonathanAllan Obrigado pela dica; espero que esta versão tenha melhor validação.
Neil
Se eu pudesse trabalhar a lógica me: p
Jonathan Allan
1

Geléia , 52 51 58 bytes

+7 bytes, descobri que o mapeamento usado não funcionava em alguns cenários (fora do exemplo) de alteração de caso.

“nḲ⁾⁶ƥ¦ṃṗḋ’b4s4‘µṙJ;U$µ€
,ŒsṢÞṪµŒlĠL€⁼2,2ȧ⁸i@€ṢeЀ¢TṪ’:3,8

Um link monádico que pega uma sequência e retorna os cinco valores distintos e consistentes a seguir:

  • [-1,-1] - entrada inválida
  • [0,0] - plano projetivo
  • [1,0] - Garrafa Klein
  • [2,0] - esfera
  • [2,1] - toro

Experimente online! ou veja a suíte de testes .

Quão?

Qualquer polígono fundamental é:

  • inalterado em rotação - pode-se virar o papel como um volante
  • inalterado sob reflexão - pode-se virar o papel ao contrário
  • inalterados caso em reversão - um de Maio de permuta as e As e / ou troca bs e Bs sem efeito - uma vez que queremos para coincidir com as direções da etiqueta real é irrelevante.

Como tal, existem nove classes de equivalência. O código cria listas de quatro números inteiros, cada um representando um exemplo de uma das nove classes de equivalência, cria as quatro rotações de cada, reflete cada uma delas e verifica se existe uma forma traduzida da entrada em cada lista. As classes são ordenadas P,P,P,K,K,K,S,S,T, portanto, pegar o número inteiro com base em 0 dividido por cada um [3,8]produz as quatro saídas válidas (a indexação é baseada em 1 e o átomo eretorna 0pela inexistência, subtraindo 1e dividindo o número inteiro por cada um dos [3,8]rendimentos [-1,-1]para o caso inválido )

“nḲ⁾⁶ƥ¦ṃṗḋ’b4s4‘µṙJ;U$µ€ - Link 1, symmetries of the 9 equivalence classes: no arguments
“nḲ⁾⁶ƥ¦ṃṗḋ’              - base 250 number                 1704624888339951310984
           b4            - convert to base 4               [1,1,3,0,1,2,2,0,1,2,3,0,0,2,2,0,1,3,1,0,2,1,2,0,2,3,1,0,3,1,2,0,2,0,2,0]
             s4          - split into 4s                   [[1,1,3,0],[1,2,2,0],[1,2,3,0],[0,2,2,0],[1,3,1,0],[2,1,2,0],[2,3,1,0],[3,1,2,0],[2,0,2,0]]
               ‘         - increment (vectorises)          [[2,2,4,1],[2,3,3,1],[2,3,4,1],[1,3,3,1],[2,4,2,1],[3,2,3,1],[3,4,2,1],[4,2,3,1],[3,1,3,1]]
                µ     µ€ - for €ach:                       ...e.g. [2,2,4,1]:
                  J      -   range of length               [1,2,3,4]
                 ṙ       -   rotate left by (vectorises)   [[2,4,1,2],[4,1,2,2],[1,2,2,4],[2,2,4,1]]
                     $   -   last two links as a monad:
                    U    -     upend (reverse each)        [[2,1,4,2],[2,2,1,4],[4,2,2,1],[1,4,2,2]]
                   ;     -     concatenate                 [[2,4,1,2],[4,1,2,2],[1,2,2,4],[2,2,4,1],[2,1,4,2],[2,2,1,4],[4,2,2,1],[1,4,2,2]]

,ŒsṢÞṪµŒlĠL€⁼2,2ȧ⁸i@€ṢeЀ¢TṪ’:3,8 - Main link: string s      e.g. "xOxO"
 Œs                               - swap case                     "XoXo"
,                                 - pair with s                   ["xOxO","XoXo"]
    Þ                             - sort by:
   Ṣ                              -   sort                        ["xOxO","XoXo"]
     Ṫ                            - tail                          "XoXo"
      µ                           - monadic chain separation, call that v
       Œl                         - convert to lowercase          "xoxo"
         Ġ                        - group indices by value        [[2,4],[1,3]]
          L€                      - length of each                [2,2]
             2,2                  - 2 pair 2                      [2,2]
            ⁼                     - equal? (1 if so, 0 if not)    1
                 ⁸                - link's left argument, v       "XoXo"
                ȧ                 - and (v if equal, 0 if not)    "XoXo"
                     Ṣ            - sort v                        "XoXo"
                  i@€             - first index for €ach          [1,3,1,3]
                         ¢        - call the last link (1) as a nilad
                       Ѐ         - map over right:
                      e           -   exists in?                  [0,0,0,0,0,0,0,0,1]
                          T       - truthy indexes                [                9]
                           Ṫ      - tail (empty list yields 0)    9
                            ’     - decrement                     8
                              3,8 - 3 pair 8                      [3,8]
                             :    - integer division (vectorises) [2,1]

Nota: 11 bytes ( ŒlĠL€⁼2,2ȧ⁸) validam apenas a sequência de entrada como tendo a forma correta - sem esse código, todos os casos de exemplo passam, exceto que ab1asão avaliados como se fossem abBaum plano projetivo.

Jonathan Allan
fonte