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.

Nick T.
źródło
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
Powiązane
Martin Ender
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.

rekurencyjny
źródło
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 ( $\).

Dennis
źródło
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.

orlp
źródło
8

FlogScript , 2 bajty

)"

(Wypróbuj na anarchii golfa .)

)Umożliwia --in-out-line-arraytryb, a reszta programu jest "odwrócenie szereg linii.

Lynn
źródło
Argh, pobiłeś mnie!
mbomb007
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.

Martin Ender
źródło
6

Haskell, 34 bajty

main=interact$concat.reverse.lines

[edytować]

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

jkabrg
źródło
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.
Reto Koradi
źródło
4

Befunge-93, 17 bajtów

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

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

Kevin W.
źródło
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.
$ 
Cyfrowa trauma
źródło
Ładne i inspirujące .
manatwork
4

Rubinowy, 16 bajtów

puts [*$<].reverse
daniero
źródło
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

Downgoat
źródło
4

Python 2, 52 bajty

import sys;print''.join(sys.stdin.readlines()[::-1])
Rozpad beta
źródło
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.

LegionMammal978
źródło
3

sed, 9 bajtów

1!G;h;$!d

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

Steve
źródło
10
Jeśli to nie twoja praca, sugeruję utworzenie wiki społeczności odpowiedzi.
lirtosiast
3

Perl, 16 bajtów

print reverse<>
Steve
źródło
@Dennis ups, teraz cofnięty.
steve
3

PowerShell, 41 bajtów

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

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

sweerpotato
źródło
3

GolfScript, 7 bajtów

n/-1%n*

Test online tutaj .

Cristian Lupascu
źródło
3

Burleska , 6 bajtów

ln<-uN

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

Lynn
źródło
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.
człowiek w pracy
źródło
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.
manatwork
źródło
Możesz usunąć „% s”
ninjalj
@ ninjalj, tylko jeśli możemy założyć, że dane wejściowe nigdy nie będą zawierać „%”.
manatwork
3

SNOBOL, 42 bajty

S S =INPUT CHAR(10) S :S(S)
 OUTPUT =S
END
ninjalj
źródło
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
człowiek w pracy
źródło
2

Wapń , 90 bajtów 86 bajtów

use IO;func main(){c=File.readLines(args[0]);for(x=c.length-1;x>=0; println(c[x--]))0;

Zobacz rozwinięty tutaj

Jacob Misirian
źródło
1
Mogę to bardzo skrócić, nadużywając forskładni. Zobacz próbkę tutaj
FryAmTheEggman
Dobra rozmowa @FryAmTheEggman! Dodałem to.
Jacob Misirian
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?

Lynn
źródło
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))
Ben Fortune
źródło
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.

Cyfrowa trauma
źródło
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.

Tom Carpenter
źródło
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])
Alex A.
źródło
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.

DLosc
źródło