Não existe um "copo meio vazio"

15

Você provavelmente conhece a pergunta retórica sobre se um copo está meio cheio ou meio vazio . Estou ficando um pouco cansado da frase, então decidi que é hora de eliminar essa confusão sobre a plenitude ou o vazio de vidro programaticamente.

Sua tarefa é escrever um programa que obtenha uma representação artística ASCII de um copo feio e produza uma arte ASCII de um copo agradável correspondente . Ele também tem que decidir se o vidro é full, mostly full, mostly emptyouempty e saída deste, bem como (4 qualquer constante, os valores de saída distintas fazer).

TL; DR

Input é uma arte ASCII de vidro ( #caracteres) e líquido (a-z ) distribuído aleatoriamente dentro e fora do copo. O líquido dentro do copo cai e se acumula no fundo; o líquido fora dele é descartado. Produza uma arte ASCII do vidro após o líquido assentar na parte inferior. Determine como o copo está cheio e produza também.

Óculos feios e agradáveis

Um copo em geral é um recipiente feito de #caracteres com fundo, duas paredes laterais e sem topo.

  • Óculos válidos não têm orifícios. (Todos os #caracteres precisam estar conectados.)
  • Haverá pelo menos dois #caracteres em cada linha da arte ASCII de entrada ou nenhum. Não haverá uma linha com exatamente uma #.
  • A linha superior da arte ASCII de entrada sempre terá exatamente dois #.
  • Óculos válidos têm exatamente um mínimo local em sua parede delimitadora de #caracteres. Isso significa que o líquido não pode ficar preso em algum lugar.
  • A parede delimitadora de um copo não terá máximos locais.
  • Não haverá nenhum #abaixo do fundo do copo.
  • O interior do vidro sempre será um espaço conectado .
  • Pode haver espaços em branco à esquerda / à direita e novas linhas na entrada.

Exemplos de óculos válidos e inválidos:

VALID (possible input to your program):

#  # 
#  # 
#### 

  #        #
   #      #
    #    #
    #    #
    #    #
     #  #
      ##

#      #
#      #
 ###   #
    #  #
    ####

#       #
 #      #
  #     #
 #      #
#       #
 ########


#   #
#   #
#   ###
#   ###
#   ###
#####


INVALID (you won't get one of those as input to your program):

#  #
   #  Has a hole.
####

#      #
   #  #  This is also considered a hole.
    ##

#   #
 # #  Less than two # on a line.
  #

## #
 # #  More than two # on the first line.
 ###

   #
 # #  Less than two # on the first line.
 ###

#               #
 #     #       #  More than one local minimum.
  #   # #     #   Liquid might get trapped.
   ###   #   #
          ###

#  #
#  #
####  Interior is not a connected space.
#  #
#  #
####

#   #
#   #######
#   ###   #
#   ##   #  Has a local maximum.
#   #   #
#      #
#     #
######

#    #
#    #
#     #
 #####
 #  #    <--- # below the bottom of the glass.

#     #
#  #  #  This is also a glass with a hole. The #'s aren't all connected.
#  #  #
#     #
#######

Um copo feio é um copo com líquido flutuando em seu interior.

  • Líquido é representado pelas letras minúsculas a-z.
  • Não haverá líquido acima da primeira linha de #caracteres. Isso significa que não é necessário permitir que o líquido caia no copo.
  • Pode haver líquido fora do vidro . Este líquido será descartado ao converter o vidro feio em um copo bonito.

Exemplos de óculos feios :

        # y    b #      i
   x   v#p  q   l#   l
  a     # a   zj # p   g
     g  #ppcg   c#
   u    #  r   n #   r
        ##########
Discard    Keep    Discard

                   <-- There will never be liquid above the glass
   #  tz  g#
    #y abc # d
 av z#ox s #  l
   c#y abth# b
   #vg y rm#   a
    ########
 e   a  b c  d     <-- Discard this as well (not within interior)

Um bom copo é um copo onde todo o líquido se acumulou na parte inferior.

  • De baixo para cima, o interior de um copo bonito consiste em várias linhas que são completamente preenchidas com letras, seguidas por no máximo uma linha que não é completamente preenchida com letras e, em seguida, várias linhas vazias.
  • Pode não haver líquido fora do interior de um copo bonito.

Conversão de um copo feio em um copo bonito

  • O líquido dentro do copo cai e se acumula na parte inferior.
  • O líquido fora do vidro é descartado.
  • Ao converter um copo feio em um copo bonito, as letras exatas devem ser preservadas. Por exemplo, se o copo feio tem três a, o bom copo também deve ter três a. (O refrigerante não se transforma subitamente em água.)
  • As letras dentro do belo copo não precisam ser encomendadas.
  • A forma do vidro deve ser preservada. Nenhum #caractere pode ser adicionado ou removido.
  • Qualquer quantidade de espaço em branco à esquerda / à direita e novas linhas é permitida.

Determinando a plenitude do vidro

  • Um copo é fullse todo o seu espaço interior estiver cheio de letras.
  • É mostly fullse 50% ou mais do espaço interior estiver preenchido.
  • É mostly emptyse menos de 50% do espaço interior for preenchido.
  • É emptyse não houver letras no copo.
  • Pode haver qualquer número de novas linhas e espaços adicionais entre o vidro artístico ASCII e a saída de plenitude.
  • O programa pode gerar valores distintos (mas constantes!) Para os 4 níveis de plenitude do vidro, não precisa imprimir as seqüências exatas acima. Especifique qual valor representa qual nível de plenitude.

Exemplos de E / S

Example 1 input:

        # y    b #      i
   x   v#p  q   l#   l
  a     # a   zj # p   g
     g  #ppcg   c#
   u    #  r   n #   r
        ##########

Example 1 output:

        #        #       
        #        #    
        #        #      
        #ppcglqb #
        #yprazjnc#    
        ##########
mostly empty

Example 2 input:

   #  tz  g#
    #y abc # d
 av z#ox s #  l
   c#y abth# b
   #vg y rm#   a
    ########
 e   a  b c  d

Example 2 output:

   #       #
    #   bc #  
     #oxysa#   
    #ygabth#  
   #vgtyzrm#    
    ########
mostly full

Example 3 input:

#      #
#  g   # f
 ###ih #  d
a c #  # e
 b  ####

Example 3 output:

#      #
#      #  
 ###  g#   
    #hi#  
    ####
mostly empty

Example 4 input:

#ab# 
#cd# 
#### 

Example 4 output:

#cb# 
#da# 
#### 
full

Example 5 input:

  #        # h
   #      #
  a #    # g
   b#    #  f
 c  #    #  
     #  #  e
   d  ##

Example 5 output:

  #        #  
   #      #
    #    #  
    #    #   
    #    #  
     #  #   
      ##
empty

Example 6 input:

# b  az#
#y s ###
###### t
  l  u

Example 6 output:

#  z   #
#ybsa###
######  
mostly full

Example 7 input:

#   # g
# b #f
#  c###
#da ### i
#  e###
##### h

Example 7 output:

#   #
#   #
#   ###
#de ###
#abc###
#####
mostly empty

Diversos

  • Isso é código de golfe, então a resposta mais curta vence.
  • Se possível, forneça um link para um intérprete online que possa ser usado para executar seu programa nas entradas de exemplo fornecidas, por exemplo tio.run
Jonathan S.
fonte
1
Esses copos são válidos? paste.ubuntu.com/26097168
l4m2
Posso sugerir: "Um copo está quase todo cheio se mais de 50% do espaço interior estiver cheio." - Se você considerar exatamente 50% como entrada inválida (sem exigir as soluções para lidar com este caso), não haverá mais um "copo meio vazio" (ou um "copo meio cheio"), combinando o título ainda melhor . Sem invalidar nenhuma solução que realmente lide com esse caso.
Anedar
1
@ l4m2 Atualizou o desafio e restringiu ainda mais a entrada. O primeiro dos seus exemplos é inválido, o segundo é válido e o terceiro é inválido.
Jonathan S.
@Anedar Embora isso possa melhorar o desafio do título, isso afastaria muito o desafio na minha opinião e, de qualquer maneira, já tem entradas inválidas suficientes. Vou deixar o caso de 50% lá.
Jonathan S.

Respostas:

12

Retina , 56 bytes

T%` l`!`^.*?#|[^#]+$
O` |\w
*`!
 
T`#!¶
*M` \w
+` \w

 +

Experimente online!

A codificação de saída é 0\n0para cheia, 0\n1vazia, 1\n0quase sempre cheia e 1\n1quase vazia (em outras palavras, o primeiro bit indica "principalmente" e o segundo bit indica "vazio").

Explicação

T%` l`!`^.*?#|[^#]+$

Começamos transformando todos os espaços e letras do lado de fora do vidro !. Isso é feito combinando um início de linha até o primeiro #ou um final de linha que não contenha um #e transliterando todos os espaços e letras nessas correspondências.

O` |\w

Classifique todos os espaços e letras. Como as letras têm pontos de código mais altos que os espaços, isso classifica todas as letras até o fim, o que significa que fica no fundo do copo. Isso também classifica as letras entre si, mas a ordem das letras no resultado é irrelevante.

*`!
 

Execução a seco: imprima o resultado da substituição de todos !por espaços, mas não aplique essa alteração na sequência de trabalho. Isso imprime o bom copo.

T`#!¶

Descarte todos #, !e linefeeds, de modo que só é deixado com os espaços e letras dentro do vidro (ainda classificadas).

*M` \w

Execução a seco: imprime o número de correspondências de um espaço seguido por uma letra. Isso encontrará no máximo uma correspondência, e somente se houver espaços e letras dentro do copo, ou seja, o copo será maioritariamente (cheio / vazio).

+` \w

Remova repetidamente um espaço seguido por uma letra. Isso "cancela" letras e espaços, de modo que acabamos apenas com o tipo de caractere que aparece com mais frequência dentro do vidro.

 +

Conte o número de correspondências desse regex, o que indica 1se há algum espaço restante (ou seja, o copo estava [quase] vazio)) e 0se não há mais (isto é, o copo estava exatamente em 50% ou mais e, portanto, [na maior parte] cheio )

Martin Ender
fonte
4

C, 190 bytes

Obrigado a @ l4m2 por salvar 17 bytes!

i,k,t,s;f(char*g){char*p=g,l[strlen(g)];for(s=t=0;*p;*p>35&&(t?l[i++]=*p:1)?*p=32:0,~*p++&t&&++s)t^=*p==35;for(k=i;i;t&*p==32?*p=l[--i]:0)t^=*--p==35;printf("%s\n%d",g,k?k-s?k*2<s?1:2:3:0);}

Saídas 0 para copo vazio, 1 para quase vazio, 2 para quase cheio e 3 para cheio.

Primeiro, passe pela seqüência de entrada contando o espaço dentro do copo, marcando as letras que estão dentro do copo e alterando todas as letras para espaços. Em seguida, passa pela corda para trás, colocando todas as letras que estavam no copo na parte inferior do copo.

Experimente online!

Desenrolado:

i,k,t,s;
f(char*g)
{
    char l[strlen(g)], *p=g;
    for (s=t=0; *p; *p>35&&(t?l[i++]=*p:1)?*p=32:0, ~*p++&t&&++s)
        t ^= *p==35;
    for (k=i; i; t&*p==32?*p=l[--i]:0)
        t ^= *--p==35;
    printf("%s\n%d", g, k?k-s?k*2<s?1:2:3:0);
}
Steadybox
fonte
variáveis globais são initally 0, portanto, não há necessidade de reinit
l4m2
@ l4m2 Obrigado, mas as funções precisam ser reutilizáveis , então eu preciso inicializar as variáveis ​​dentro da função. Exceto iparece, pois a função sempre deixa seu valor em 0 no final.
Steadybox
· Char * malloc (strlen (g)) · pode ser char l[strlen(g)]se C99 permitido, como é mais curto e não fazem vazamento de memória
l4m2
t = *p-35 ? t : !t-> t ^= *p==35se t é sempre 0 ou 1
l4m2 2/17/17
&&(*p=32)-> ?*p=32:0 char l[strlen(g)],*p=g->char*p=g,l[strlen(g)]
l4m2
1

Python 2 , 342 bytes

import re
def f(g):
 g=[l for l in g if'#'in l];s,w,l,W=zip(*[re.findall(r'([^#]*)(#+)'*2,l)[0] for l in g[:-1]]);a=sorted(''.join(l));R=len(a);r=a.count(' ');L=[]
 for x in l:L+=[''.join(a[:len(x)])];a=a[len(x):]
 for l in zip([' '*len(x)for x in s],w,L,W)+[re.sub('[^#]',' ',g[-1]),'mostly '*(0<r<R)+['full','empty'][r>R/2]]:print''.join(l)

Experimente online!

TFeld
fonte
1

Perl 5 , 197 bytes

map{/#([^#]+)#/;$l.=$1;y/#/ /c}@a=grep/#/,<>;$f=length$l;$_=$l=~y/ //d/$f;$a[--$i]=~s/#( +)#/'#'.(substr$l,0,($q=length$1),"").$"x($q-$p).'#'/e while$p=length$l;say for@a;say'm'x($_!=int),$_>.5?e:f

Experimente online!

Saídas:

 e  empty
me  mostly empty
mf  mostly full
 f  full
Xcali
fonte