Frases invertidas

15

O objetivo deste desafio é receber uma entrada e saída dessa entrada, mas com a ordem da sentença invertida. Exemplo de entrada:

Hello friend. What are you doing? I bet it is something I want to do too!

Saída de exemplo:

I bet it is something I want to do too! What are you doing? Hello friend.

Como você pode ver nos exemplos, seu programa precisa lidar com pontos de interrogação, pontos de exclamação e pontos. Você pode assumir que cada sentença tem uma pontuação e um espaço antes da próxima sentença. Os espaços à direita / novas linhas estão ok, desde que sejam legíveis. O menor código vence.

Boa sorte!

EDIT: Você pode assumir que as frases não têm aspas ou parênteses, mas se você tornar seu código capaz de lidar com ambos, obterá -5 bytes Exemplo de saída para parens / aspas:

"Hello, " she said. (I didn't know what she was talking about.) --> (I didn't know what she was talking about.) "Hello, " she said.

fonte
Podemos supor que não haverá aspas ou parênteses? Caso contrário, como lidamos com eles?
BrainSteel
Fiz uma edição na postagem esclarecendo isso.
Você pode dar um exemplo da saída esperada para uma frase que contém aspas ou parênteses, por favor?
Mbomb007
6
Se uma frase possui pontuação entre aspas ou parênteses, como devemos lidar com isso?
Isaacg
2
@ Scimonster Você quer dizer "ie", etc., certo? Ah, e por favor corrija minha citação do caso de teste para:"Hello!" she said. (I hesitated. How should I respond? This is too much!) I responded, "Hi there. How are you? What is your cat's name?" without thinking any more about it.
Não é que Charles

Respostas:

9

Julia, 45 42 bytes - 5 bônus = 37

s->join(reverse(split(s,r"[.?!]\K "))," ")

Isso cria uma função anônima que aceita uma string como entrada e retorna a string com suas frases invertidas. Ele lida com qualquer caractere especial de maneira apropriada, embora as aspas duplas e os cifrões devam ser escapados, caso contrário, não são cadeias válidas em Julia.

Ungolfed + explicação:

function f(s)
    # Get individual sentences by splitting on the spaces that
    # separate them. Spaces are identified by matching punctuation
    # then moving the position beyond that match and matching a
    # space. This is accomplished using \K.

    sentences = split(s, r"[.?!]\K ")

    # Reverse the order of the array of sentences.

    reversed_order = reverse(sentences)

    # Join the array elements into a string, separated by a space.

    join(reversed_order, " ")
end

Exemplos:

julia> f("Hello friend. What are you doing? I bet it is something I want to do too!")
"I bet it is something I want to do too! What are you doing? Hello friend."

julia> f("\"Hello, \" she said. (I didn't know what she was talking about.)")
"(I didn't know what she was talking about.) \"Hello, \" she said."

E se você não gosta de olhar as aspas escapadas na saída:

julia> println(f("\"Hello, \" she said. (I didn't know what she was talking about.)"))
(I didn't know what she was talking about.) "Hello, " she said.

Economizou 3 bytes na expressão regular graças a Martin Büttner! Anteriormente, este usou um lookbehind: (?<=[.?!]).

Alex A.
fonte
Eu não acho que isso se qualifique para o bônus ...
Optimizer
@ Optimizer: Como não? Funciona como esperado entre parênteses, aspas, etc., conforme indicado no post.
18715 Alex A.
Você pode fornecer um link on-line para testar, com o exemplo da seção de bônus da pergunta.
Optimizer
@Optimizer: a única maneira de executar uma versão recente do Julia online requer registro e não oferece suporte a links permanentes. Seria suficiente incluir simplesmente entrada e saída aqui no post?
18715 Alex A.
Claro, eu acho ..
Optimizer
7

CJam, 23 22 bytes

Não tenho certeza se isso se qualifica para o bônus ou não, mas aqui vai a solução:

Sq{1$".?!"-{])[}|}%]W%

Expansão do código (pouco desatualizado) :

Sq+                      e# Read the input and prepend with a space
   {            }%       e# For each input character
    _".?!"&              e# Copy and check if its one of ., ? and !
           {][}&         e# If it is one of the above, wrap everything till now in an array
                         e# and start a new array to be wrapped next time we get one of those
                         e# three characters. We now have an array of strings, each having
                         e# a single sentence
                  W%     e# Reverse the ordering of these sentences
                    s(   e# Convert to string and remove the first space

Experimente online aqui

Optimizer
fonte
Ah, você fez esse post logo depois que eu o editei. Você ganha um bônus de -5 agora (apenas para dificultar um pouco) Então, um bônus de -5 para você! 18 bytes, uau, não tenho certeza se isso é imbatível: P
5

J, 35 32

Ele quase lida com entrada de bônus, exceto que eu tenho que escapar de apóstrofos únicos, então acho que não conta. (Além disso, minha primeira submissão aqui)

f=.;@|.@(]<;.2~'.?!'e.~])@,~&' '

Uso:

f 'Hello friend. What are you doing? I bet it is something I want to do too!'
Adrian17
fonte
4

Perl, 27/25

#!perl -n
print reverse/ |[^.!?]*./g

Ou na linha de comando:

$perl -nE'say reverse/ |[^.!?]*./g'
nutki
fonte
Agradável! Você pode obter o bônus de -5 perl -nE 'say reverse/ |[^.?!]*.\)?/g', elevando sua contagem total para 23.
ThisSuitIsBlackNot 15/15/15
2

PHP, 60

echo join(' ',array_reverse(preg_split('/(?<=[?!.])/',$s)));
romaninsh
fonte
Você pode usar o regex [?!.]\K?
Martin Ender
Além disso, isso não adiciona espaços adicionais à sequência, a menos que você inclua o espaço no padrão para dividir?
Martin Ender
@ MartinBüttner, não, não poderei restaurar o sinal correto ao juntar os dados novamente, por isso precisamos de algo que não consuma o personagem.
romaninsh
2

Bash + coreutils, 40 bytes

sed 's/\([?.!]\) */\1\n/g'|tac|tr \\n \ 

Como lê STDIN, a entrada pode ser redirecionada a partir de um arquivo ou simplesmente canalizada, por exemplo:

$ printf 'Hello friend. What are you doing? I bet it is something I want to do too!' | sed 's/\([?.!]\) */\1\n/g'|tac|tr \\n \ 
I bet it is something I want to do too! What are you doing? Hello friend. 
$ 
Trauma Digital
fonte
Isso realmente funciona entre parênteses no sentido, que (foo bar.)é trocado como uma unidade?
Martin Ender
@ MartinBüttner Parece que a pergunta foi editada, então não posso mais reivindicar o bônus :(
Digital Trauma
2

Pip , 25 bytes

a.:sRV(a^@2+$ALa@*^".?!")

Depois de anexar um espaço para a cadeia de entrada, encontramos todos os índices de ., ?e! , adicione 2, e usar o ^@split-no operador para quebrar a string em sentenças (cada um com um espaço à direita). Inverta a lista e é impressa automaticamente no final do programa. Voilà!

Exemplo mostrando os estágios da computação principal com entrada A! B? C. D!:

              ^".?!"     ["." "?" "!"]
           a@*           [[7] [4] [1 10]]
        $AL              [7 4 1 10]
      2+                 [9 6 3 12]
   a^@                   ["A! " "B? " "C. " "D! "]
RV(                 )    ["D! " "C. " "B? " "A! "]

                         D! C. B? A! 
DLosc
fonte
Não, você não :) :)
Optimizer
2

Retina , 61 34 33 30 bytes

Créditos ao nutki por reduzi-lo em 24 bytes.

^
#
+`(#.*[.!?]) (.+)
$2 $1
#
<empty>

Onde <empty>significa uma linha vazia. Isso pressupõe que isso #não faz parte da entrada, mas se isso não for legítimo, eu poderia trocá-la por qualquer outro personagem, incluindo "(que eu precisaria lidar apenas com o bônus) ou algo imprimível. Você pode executar o código como esse em um único arquivo se usar o-s sinalizador ou colocar cada linha em um arquivo separado e passá-las para a Retina.

É possível reverter isso com uma única substituição de regex, mas é realmente complicado. Mesmo nos grupos de balanceamento do .NET, eu precisava de algo em torno de 90 bytes, então tentei fazê-lo em várias etapas.

Na Retina, todo par de linhas é um estágio de substituição, onde a primeira linha é o padrão e a segunda linha é a substituição.

^
#

Este estágio simplesmente prepara a string para processamento adicional. Anexa a #como um marcador. Esse marcador indica que tudo à sua frente já foi colocado no lugar certo e tudo depois ainda precisa ser processado.

+`(#.*[.!?]) (.+)
$2 $1

Esse estágio troca as sentenças, movendo repetidamente a última sentença na frente da #(que se move para a frente na sequência no processo). O +`instrui a Retina a repetir esse estágio até que a saída pare de mudar. Como um exemplo, aqui está como a entrada foo. bar! blah?seria processada:

#foo. bar! blah?
blah? #foo. bar!
blah? bar! #foo.

E, finalmente, simplesmente removemos o marcador:

#
<empty>
Martin Ender
fonte
Por que não apenas .+=> $0 #e repetido (.*?[.!?] )(.*#)=> $2$1?
nutki
@nutki Oh, isso é muito melhor, obrigado. :)
Martin Ender
1

Java, 113

s->{String t[]=s.split("(?<=[\\.?!]) "),u="";for(int i=t.length;i-->0;)u+=t[i]+" ";return u.replaceAll(".$","");}
Ypnypn
fonte
1

JavaScript (ES6) 47 45

Como afirmado, é um exercício simples de regex. Em javascript:

// ES6 - FireFox only
F=t=>t.match(/\S[^.!?]+./g).reverse().join(' ')

// ES5 - so much longer
function G(t){return t.match(/\S[^.!?]+./g).reverse().join(' ')}

// TEST

alert(G("Hello friend. What are you doing? I bet it is something I want to do too!"))
 

edc65
fonte
Eu ia fazer javascript, mas você me venceu.
21815 BobTheAwesome
Isso produz espaços extras antes de tudo, exceto a última frase (originalmente a primeira). Não tenho certeza se está OK, pois a tarefa não está muito bem definida.
nutki
@nutki sim, eu concordo. Corrigido
edc65 15/05
1

Python 2, 62

Não vai melhorar o bônus, pois provavelmente não vale o custo de bytes.

import re
print' '.join(re.split('(?<=[?!.]).',input())[::-1])
mbomb007
fonte
Isso não se qualifica para o bônus. Veja o exemplo de bônus na pergunta
Otimizador
@Optimizer Veja o histórico de perguntas. No momento em que atualizei minha pergunta para adicionar o bônus, minha saída correspondia ao exemplo. Não havia nada indicando que o parêntese poderia estar fora de um período.
Mbomb007
Eu acho que a intenção era essa apenas desde o começo. Um exemplo sólido veio mais tarde. Não significa que você ainda receber o bônus :) (I removido meu também)
Optimizer
1

Matlab (93 bytes)

y=[32 input('','s')];y=sortrows([cumsum(ismember(y,'?!.'),'reverse');y]',1)';disp(y(4:2:end))
  • Isso pressupõe que a entrada não contenha espaços à esquerda ou à direita
  • Usa entrada e saída padrão
  • Testado no Matlab 2014b
Luis Mendo
fonte
1

Ruby 41

As outras respostas do Ruby não têm WTF suficiente.

#!ruby -apF(?<=[.!?])\s
$_=$F.reverse*" "

Isso pelo menos funciona no Ruby 2. Se a opção ae Ffuncionar na 1.8.7, acho que você pode soltar $_=para salvar três caracteres.

Inverte todas as linhas no stdin e imprime no stdout:

$ ruby foo.rb <<< "Hello. Hi. How are you? Good, you? fine, thanks."
fine, thanks. Good, you? How are you? Hi. Hello.
daniero
fonte
Poderia explicar a resposta.
Mhmd
1

Ruby, 48 (42 sem os putts) bytes

reverse_sentence.rb

puts $*[0].scan(/\S[^.!?]+./).reverse.join(" ")

Uso:

ruby reverse_sentence.rb 'Hello friend. What are you doing? I bet it is something I want to do too!'

Resultado:

I bet it is something I want to do too! What are you doing? Hello friend.

Criticism more than welcome.

DickieBoy
fonte
2
Criticism: You spelled "sentence" incorrectly.
Alex A.
save 6 characters: .join(" ") => *" "
daniero
@AlexA. Best feedback ever!
DickieBoy
@daniero thanks, nice to know
DickieBoy
1

k, 31

{1_,/|(0,1+&x in"?!.")_x:" ",x}

.

k){1_,/|(0,1+&x in"?!.")_x:" ",x} "Hello friend. What are you doing? I bet it is something I want to do too!"
"I bet it is something I want to do too! What are you doing? Hello friend."
tmartin
fonte
0

C# - LINQPAD - 93 - 5 = 88 bytes

void Main(){string.Join(" ",Regex.Split(Console.ReadLine(),"(?<=[.?!]) ").Reverse()).Dump();}

C# Console App 189 - 5 = 184 bytes

using System;using System.Linq;using System.Text.RegularExpressions;class P{static void Main(){Console.WriteLine(string.Join(" ",Regex.Split(Console.ReadLine(), "(?<=[.?!]) ").Reverse()));}}

regex shamelessly flogged from Alex A. :)

jzm
fonte
You can save 7 bytes by putting your application in namespace System then within that using Linq;usingText.RegularExpressions saving 2x system.
ldam
I don't think that this qualifies for the bonus. Look at the bonus example in the question
Optimizer
0

Clojure - 44 71 chars

(defn rs[s](reverse(re-seq #"\S.+?[.!?]"s)))

Improved and simplified RE, eliminated unnecessary whitespace.

Output is a sequence of the sentences in the original string, with the order of the sentences reversed:

Input: "Hello friend. What are you doing? I bet it is something I want to do too!" Output: ("I bet it is something I want to do too!" "What are you doing?" "Hello friend.")

Bob Jarvis - Reinstate Monica
fonte
0

Ruby, 47

$><<gets.strip.split(/(?<=[.?!]) /).reverse*' '

credits to Martin Büttner, for saving some characters.

Mhmd
fonte
1
You can read the input from STDIN with gets to save a byte, print it with $><< to save byte (no need for a space) and join the string with *'' to save two bytes.
Martin Ender
@MartinBüttner thanks for the suggestion, I wouldn't go with reading from the input from STDIN, though. Simply because there will be a trailing new line.
Mhmd
Actually, I think your code will currently result in a leading space.
Martin Ender
mmm, you're right. I'll see what should I do.
Mhmd
0

CJam, 21 bytes

1q{1?_"!.?"-}%1a/W%S*

This works by turning spaces after !s, .s and ?s into the number 1 (not the character 1 nor the character with code point 1, so the input can still contain those), splitting at 1's, reversing the order of the resulting chunks and joining by spaces.

Try it online in the CJam interpreter.

How it works

1                     e# B := 1
 q                    e# Q := input()
  {         }%        e# for each C in Q (map):
   1?                 e#   C := B ? C : 1
     _"!.?"-          e#   B := string(C).strip("!.?")
              1a/     e# Q := Q.split([1])
                 W%   e# Q := reverse(Q)
                   S* e# Q := Q.join(" ")
                      e# print(Q)
Dennis
fonte