Implementuj „tac”: Drukuj wiersze z pliku w odwrotnej kolejności


30

Pomiędzy pytaniem o kotka a tym pytaniem w U&L o sedmagii, co powiesz na wdrożenie tac?


Cel

Zaimplementuj program, który odwróci i wydrukuje linie w pliku.


Wkład

Plik podany jako nazwa lub przez standardowe wejście


Wydajność

Linie odwrócone do standardowych.


Punktacja

Bajty kodu źródłowego.


9
tacjest trochę dziwne, jeśli chodzi o końcowe linie. Przekształca a\nb\n(trailing linefeed) w b\na\ni a\nb(bez trailing linefeed) w ba\n. Czy tak ma zachowywać się nasz kod?
Dennis


10
Ponadto, jeśli musimy odtworzyć zachowanie tac, 3-bajtowe odpowiedzi Bash, które się wykonują, tacto tylko kwestia czasu ...
Dennis

1
@Dennis w tym miejscu prawdopodobnie najlepiej pozostawić niezdefiniowany.
Nick T

1
@Dennis Ma dla mnie sens. Wizualizuj linie pliku jako poziome rzędy, wszystkie zakończone na \n. tacodwraca kolejność tych wierszy. Jeśli an \nzostanie usunięty ze środka pliku, zakończony wiersz zostanie dołączony do następnego wiersza, ale w przypadku ostatniego wiersza nie ma następnego wiersza do przyłączenia.
Blacklight Shining

Odpowiedzi:


15

GS2, 3 bajty

* +

Te trzy bajty to kolejno linie podzielone, odwrócone i połączone.


9

Perl, 11 bajtów

$\=$_.$\}{

Zachowuje się dokładnie jak tac. Ten kod wymaga -pprzełącznika, który policzyłem jako 1 bajt.

Przebiegi testowe

$ echo -en 'a\nb' | perl -pe'$\=$_.$\}{' | xxd -g 1
0000000: 62 61 0a                                         ba.
$ echo -en 'a\nb\n' | perl -pe'$\=$_.$\}{' | xxd -g 1
0000000: 62 0a 61 0a                                      b.a.

Jak to działa

Jak wyjaśniono tutaj , -pprzełącznik zasadniczo otacza while (<>) { ... ; print }program, więc kod źródłowy jest równoważny

 while(<>)
 {
   $\ = $_ . $\
 }
 print

Dla każdego wiersza danych wejściowych wstawiamy bieżącą linię ( $_) do $\(początkowo niezdefiniowana), aktualizując ją o wynik.

Po przetworzeniu wszystkich wierszy printwypisuje wartość zmiennej lokalnej $_(niezdefiniowanej w tym zakresie), a następnie separator rekordów wyjściowych ( $\).


Chcesz wyjaśnić, jak to działa?
xebtl

2
@xebtl Evilly. Dodanie -pprzełącznika powoduje zawinięcie kodu w pętlę, która zaczyna się while(<>){i kończy } continue { print }, co pozwala na filtrowanie danych wejściowych poprzez modyfikację $_. $\=$_.$\wstawia każdą linię wejściową do terminatora rekordu wyjściowego, a przedwcześnie }{kończy whileblok dostarczany przez perl , więc continueblok nie jest już do niego dołączany. Tak więc wszystkie wiersze wejściowe są dodawane $\w odwrotnej kolejności, a następnie na końcu continue { print }ostatecznie działa, wypisując „nic” ( $_będzie niezdefiniowane po zakończeniu wprowadzania), ale z terminatorem $\.
hobbs

@xebtl grr, formatowanie kodu w komentarzach wydaje się nieco zepsute, gdy odwrotne ukośniki i odwrotne znaki zbliżają się do siebie. Być może możesz zgadnąć, co próbowałem powiedzieć.
hobbs

1
@primo Pierwszy przykład pokazuje, co dzieje się w tym przypadku. Wynik będzie dziwny, ale dokładnie taki jak tac.
Dennis

1
@Dennis strony 18 i następne tej książki
msh210

8

Pyth, 4 bajty

j_.z

.zto wejście oddzielone liniami jako lista, _odwraca je i jłączy znakiem, którym domyślnie jest \n.



7

Siatkówka , 7 bajtów

!rm`.*$

Z jednym wyrażeniem regularnym Retina działa w trybie dopasowania. Zwykle drukuje to tylko liczbę dopasowań, ale !konfigurujemy go tak, aby zamiast tego wyświetlał rzeczywiste dopasowania (oddzielone liniami).

Rzeczywiste wyrażenie regularne jest tylko .*$. .*dopasowuje dowolną linię (potencjalnie pustą), ponieważ .może pasować do dowolnego znaku oprócz linii. Dotrę $za chwilę.

Jak sprawić, by wydrukował mecze w odwrotnej kolejności? Korzystając z trybu dopasowywania od prawej do lewej platformy .NET, aktywowanego za pomocą r. Oznacza to, że silnik wyrażeń regularnych uruchamia się na końcu łańcucha podczas wyszukiwania dopasowań i działa wstecz.

Wreszcie, msprawia, że $dopasowanie jest końcem linii zamiast końca łańcucha. Dlaczego tego potrzebujemy? Problem polega na tym, że .*generuje obce dopasowania. Rozważ podstawienie wyrażenia regularnego

s/a*/$0x/

zastosowane do danych wejściowych baaababaa. Można by pomyśleć, że to przyniesie baaaxbaxbaax, ale tak naprawdę daje baaaxxbaxxbaaxx. Czemu? Ponieważ po dopasowaniu aaakursor silnika znajduje się między aa b. Teraz nie może dopasować więcej as, ale a*jest również zadowolony z pustego ciągu. Oznacza to, że po każdym pojedynczym meczu otrzymujesz kolejny pusty mecz.

Nie chcemy tego tutaj, ponieważ wprowadziłoby to dodatkowe puste linie, dlatego odrzucamy te obce dopasowania (które są na początku linii ze względu na tryb od prawej do lewej), wymagając, aby dopasowania zawierały koniec linia.


6

Haskell, 34 bajty

main=interact$concat.reverse.lines

[edytować]

Zapisano jeden bajt, zastępując unlinesgo concat.


4

CJam, 7 bajtów

qN/W%N*

Czyta standardowe wejście, drukuje na standardowe wyjście.

Wyjaśnienie:

q       Get input.
N/      Split at newlines.
W%      Reverse list.
N*      Join with newlines.


4

Befunge-93, 17 bajtów

~:1+!#v_
>:#,_@>$

Nic szczególnego; po prostu połóż wszystko na stosie, a następnie zdejmij.


4

Pure Bash (bez zewnętrznych narzędzi), 56

mapfile a
for((i=${#a[@]};i--;));{
printf %s "${a[i]}"
}

Jest to jedna z nielicznych odpowiedzi na dokładną tacemulację, o którą pytano w komentarzu Dennisa :

$ echo -en 'a\nb' | ./tacemu.sh | xxd -g 1
0000000: 62 61 0a                                         ba.
$ echo -en 'a\nb\n' | ./tacemu.sh | xxd -g 1
0000000: 62 0a 61 0a                                      b.a.
$ 

Ładne i inspirujące .
manatwork


4

JavaScript (SpiderMonkey Shell), 38 bajtów

[...read(readline())].reverse().join``

Dość proste


read() czyta plik

readline() odczytuje ciąg ze STDIN

[...str]podzieli str na tablicę znaków

reverse() odwróci tablicę

join`` zwinie tablicę w ciąg


4

Python 2, 52 bajty

import sys;print''.join(sys.stdin.readlines()[::-1])

1
Czy input () nie czyta jednej linii ze standardowego wejścia?
Lynn

@Mauris Edytował to
Beta Decay

Co import sys;print sys.stdin.read()[::-1]?
dieter

@dieter To odwraca każdą postać, wyzwanie wymaga jedynie odwrócenia linii
Beta Decay

ok moje złe - nie przeczytałem go uważnie, przepraszam
dieter

4

C #, 179 171 bajtów

using B=System.Console;class A{static void Main(){var a=new System.Collections.Stack();string b;while((b=B.ReadLine())!=null)a.Push(b);foreach(var c in a)B.WriteLine(c);}}

Odczytuje wiersze, umieszczając je na stosie, a następnie zapisuje je do tyłu. Użyłbym do tego Mathematiki, ale nie ma poczucia EOF.


3

sed, 9 bajtów

1!G;h;$!d

To nie jest pożądane, to słynny sed liniowy.


10
Jeśli to nie twoja praca, sugeruję utworzenie wiki społeczności odpowiedzi.
lirtosiast


3

PowerShell, 41 bajtów

$a=$args|%{gc $_};[array]::Reverse($a);$a

Przechowuje zawartość pliku linia po linii a, odwraca ai ostatecznie drukuje.



3

Burleska , 6 bajtów

ln<-uN

lndzieli linie, <-odwraca, uNłączy linie i formaty dla surowego wyjścia.


3

Bash, 48 43 znaków

(Zainspirowany Cyfrowy Trauma „s bash odpowiedź . Upvotes dla idei powinien udać się do niego.)

mapfile -c1 -C's=$2$s;set'
printf %s "$2$s"

Przykładowy przebieg:

bash-4.3$ echo -en 'a\nb' | bash tac.sh | xxd -g 1
0000000: 62 61 0a                                         ba.

bash-4.3$ echo -en 'a\nb\n' | bash tac.sh | xxd -g 1
0000000: 62 0a 61 0a                                      b.a.

Myślę, że możesz to zrobić mapfile -c1 -Cfzamiast mapfile -c1 -Cf a.
Digital Trauma

Poprawny. W międzyczasie też to odkryłem, -Cnajpierw wypróbowałem coś tak trudnego .
manatwork

3

GNU Awk, 27 znaków

(Zainspirowany Ed Morton „s GNU awk odpowiedzi . CW, bo nie ma na celu przejąć jego rozwiązanie).

{s=$0RT s}END{printf"%s",s}

Zauważ, że zmieniając RTRSstaje się to przenośny standardowy Awk, ale traci on zdolność do zachowania braku końcowej nowej linii.

Przykładowy przebieg:

bash-4.3$ echo -en 'a\nb' | awk '{s=$0RT s}END{printf"%s",s}' | xxd -g 1
0000000: 62 61 0a                                         ba.

bash-4.3$ echo -en 'a\nb\n' | awk '{s=$0RT s}END{printf"%s",s}' | xxd -g 1
0000000: 62 0a 61 0a                                      b.a.

Możesz usunąć „% s”
ninjalj

@ ninjalj, tylko jeśli możemy założyć, że dane wejściowe nigdy nie będą zawierać „%”.
manatwork


2

Gema, 25 znaków

*\n=@set{s;$0${s;}}
\Z=$s

Przykładowy przebieg:

bash-4.3$ echo -en 'a\nb' | gema '*\n=@set{s;$0${s;}};\Z=$s'
ba

bash-4.3$ echo -en 'a\nb\n' | gema '*\n=@set{s;$0${s;}};\Z=$s'
b
a


2

sed, 7 bajtów

G;h;$!d

To działa dla mnie (i jest to najkrótsze rozwiązanie gdzie indziej), ale tak naprawdę nie chcę wiedzieć, dlaczego. Dopiero co pomieszałem ze słynną 9-bajtową sztuczką, dopóki jej nie znalazłem. Zgaduję, Gże pierwsza linia nic nie robi?


2
Właściwie coś robi: twój kod tworzy dodatkowy znak nowej linii na końcu wyniku. ( Gdodaje nową linię i zawartość przestrzeni wstrzymania do przestrzeni wzorów. Podczas gdy dodawanie zawartości pustej przestrzeni przechowywania jest rzeczywiście nieszkodliwe, nowa linia jest nadal dołączana.)
manatwork

2

JavaScript (Node.js), 91 bajtów

console.log(require('fs').readFileSync(process.argv[2])+"".split(d="\n").reverse().join(d))

Miałeś na myśli console.log((require('fs').readFileSync(process.argv[2])+"").split(d="\n").reverse().join(d))(92 bajty)? Twój obecny kod nie odwraca linii.
Szczoteczka do zębów

2

Bash + wspólne narzędzia, 25

tr \\n ^G|rev|tr ^G \\n|rev

Oto ^Gdosłowna BELpostać. Zakładam, że dane wejściowe można wydrukować tylko w ascii.

Ten transforms całą wejście do jednej linii, zastępując znaki nowej linii z taśm, następnie reverses tę linię, następnie transforms powrotem do multilinii, następnie reverses każdą linię ponownie, aby uzyskać pożądany wynik.


2

MATLAB, 44

@(x) strjoin(fliplr(strsplit(x,'\n')),'\n');

Dzieli ciąg w nowych wierszach, odwraca wynikową tablicę, a następnie ponownie dołącza nowe znaki linii.


2

Julia, 65 bajtów

open(s->print(join(reverse([l for l=readlines(s)]),"")),ARGS[1])

Pobiera to plik jako argument wiersza poleceń i wypisuje jego wiersze w odwrotnej kolejności. Końcowe znaki nowej linii są przenoszone na przód, w przeciwieństwie do tac, co jest zgodne z prawem.

Nie golfowany:

function p(s::Stream)
    # Create a vector of the lines of the input stream
    L = [l for l in readlines(s)]

    # Reverse the vector and join it back into a string
    j = join(reverse(L), "")

    # Print the string to STDOUT
    print(j)
end

# Open the file specified in the first command line argument
# and apply the function p to its contents
open(p, ARGS[1])

2

Pip , 3 + 2 = 5 bajtów

Wykorzystuje flagi ri n; czyta ze standardowego.

RVg

The rFlag odczytuje stdin i zapisuje go jako lista wierszy g(który normalnie jest lista linii poleceń ar g ów). Następnie odwracamy tę listę i jest ona automatycznie drukowana. Do nlisty przyczyny flag być wyjście z nowej linii jako separatora.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.