Viết chương trình đảo ngược tên của tệp nguồn của nó


27

Trong một tệp duy nhất, viết chương trình không yêu cầu đầu vào và không tạo đầu ra. Khi chạy, nó sẽ đảo ngược tên của tệp mà nó được chứa trong đó, bất kể tên đó là gì , mà không làm thay đổi mã hoặc tạo ra các tác dụng phụ kéo dài khác.

Bất kỳ cách nào để đạt được điều này là tốt. Điều quan trọng là một khi chương trình được chạy, thay đổi duy nhất là tên tệp của nó đã bị đảo ngược. ví dụ: không có tập tin mới nào trong thư mục

Chạy chương trình một lần nữa nên đảo ngược tên trở lại. Thật vậy, chương trình sẽ có thể được chạy tùy ý nhiều lần.

Đối với mục đích của thách thức này:

  • Bạn có thể giả sử tên tệp luôn là chuỗi các chữ cái viết thường (az) dài từ 1 đến 127 ký tự. (Nếu ngôn ngữ của bạn yêu cầu các tệp phải có tiện ích mở rộng để chạy thì chỉ cần đảo ngược phần trước phần mở rộng, ví dụ mycode.batedocym.bat.)
  • Bạn có thể giả sử tệp mã nằm trong một thư mục để nó không có xung đột đặt tên (ngoại trừ chính nó).
  • Bạn có thể không cho rằng tên tệp không phải là một bảng màu, tức là giống nhau khi bị đảo ngược. Tên tập tin là palindromes nên hoạt động tốt như những tên không.
  • Bạn có thể đọc nội dung hoặc siêu dữ liệu của tệp. Không có hạn chế ở đây.
  • Bạn có thể cho rằng chương trình của bạn sẽ được chạy trên một hệ điều hành phổ biến, hiện đại (cụ thể là Windows / Linux), vì không phải tất cả các hệ vỏ đều có cùng một bộ lệnh.

Như một ví dụ cụ thể, giả sử bạn có một chương trình Python trong một tệp được gọi mycodetrong thư mục riêng của nó. Đang chạy

python mycode

trong thiết bị đầu cuối sẽ dẫn đến tên tệp được đảo ngược thành edocym. Tệp edocymphải ở một mình trong thư mục của nó - không có tệp nào được đặt tên mycodenữa. Đang chạy

python edocym

sẽ đảo ngược tên trở lại mycode, tại đó quá trình có thể được lặp lại vô thời hạn.

Nếu cùng một tệp Python đã được đổi tên racecar(không thay đổi mã) và sau đó chạy

python racecar

không có gì thay đổi rõ rệt vì "racecar" là một bảng màu. Điều đó cũng tương tự nếu tên tệp là, nói, ahoặc xx.

Mã ngắn nhất tính bằng byte thắng. Tiebreaker là câu trả lời bình chọn cao hơn.


Liệu thư mục làm việc hiện tại có vấn đề?
Brad Gilbert b2gills

@ BradGilbertb2gills Bạn sẽ có thể sao chép thư mục với chương trình sang một nơi khác và vẫn hoạt động (giả sử bạn có quyền và không có gì). Bạn có thể giả sử thư mục làm việc của shell sẽ là thư mục chứa tập tin.
Sở thích của Calvin

6
Điều gì nếu chúng ta đang sử dụng một ngôn ngữ biên dịch? Làm thế nào để thực thi ảnh hưởng đến quy tắc của bạn?
EMBLEM

Yêu cầu làm rõ 'chấp nhận không có đầu vào và không tạo ra đầu ra'. Về mặt kỹ thuật, tên của tệp là một đầu vào phải được lấy từ hệ thống tệp và tên đã thay đổi phải được gửi đến hệ thống tệp. Đây là đầu vào và đầu ra. Nó có thể đáng giá để xác định rằng không có đầu ra khác được cho phép.
atk

Ngoài ra, bạn có coi việc sử dụng các quy trình con là vi phạm quy tắc đầu vào / đầu ra không? Nghĩa là, gọi một quy trình riêng để thực hiện một phần của nhiệm vụ, như đảo ngược tên, sẽ yêu cầu gửi tên cho quy trình khác (đầu ra từ mã của bạn và nhập vào ứng dụng) và nhận giá trị từ quy trình (đầu ra của quy trình và nhập vào ứng dụng).
atk

Câu trả lời:


41

Bash + tiện ích linux phổ biến, 13 byte

Phương pháp của tôi tương tự như @ DigitalTrauma nhưng ngắn hơn một chút do đường ống có ls:

mv * `ls|rev`


20
Chào mừng bạn đến với Câu đố lập trình & Code Golf! Đây là một câu trả lời đầu tiên rất tốt đẹp. :)
Alex A.

1
Chỉ hoạt động nếu không có tệp khác trong thư mục.
WGroleau

1
@WGroleau && terdon: cả hai nhận xét của bạn đều đúng nhưng câu hỏi đã xử lý 2 giả định đó.
Julie Pelletier

@JuliePelletier ah, vâng, bạn hoàn toàn đúng. Tôi đã bỏ lỡ rằng tên tập tin chỉ có thể bao gồm các chữ cái viết thường.
terdon

14

C #, 153 byte

void f(){var x=System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name;File.Move(x,new string(x.Reverse().ToArray()).Substring(4)+".exe");}

OO rất tuyệt và cho đến khi bạn có một biến được xác định:

System.Reflection.Assugging.GetExecutingAssugging (). ManifestModule.Name

điều đó chỉ có nghĩa


12

Bash + tiện ích linux phổ biến, 15

  • Lưu 1 byte nhờ @Dennis

Giả sử rằng tập lệnh nằm trong một thư mục của chính nó.

mv * `rev<<<$0`

6
Bạn có thể giả sử tệp mã nằm trong một thư mục , vì vậy $0có thể được thay thế bằng *.
Dennis

Xin lỗi nhưng có một lỗi nhỏ trong bản cập nhật của bạn và nó không hoạt động như hiện tại. Cách khắc phục đơn giản nhất là quay lại gần hơn với những gì bạn đã có trước $0đó thay vì cuối cùng *.
Julie Pelletier

@JuliePelletier Nó dường như hoạt động trước đây khi tôi thử nó, nhưng vâng, bạn đúng - * mở rộng toàn cầu không xảy ra ở bên phải của a <<<.
Chấn thương kỹ thuật số

7

Julia, 51 byte

d,f=splitdir(@__FILE__)
cd(d)do
mv(f,reverse(f))end

Chương trình này phải là hệ điều hành bất khả tri, mặc dù nó chỉ được thử nghiệm trên OS X.

Ung dung:

# Get the directory and file name of the current source file
d, f = splitdir(@__FILE__)

# Change the working directory temporarily to d
cd(d) do
    # Overwrite the file with the reverse of its name
    mv(f, reverse(f))
end

8
Chúc mừng! 20k !!!
Luis Mendo

Hầu hết các câu trả lời dường như cho rằng tệp nằm trong thư mục hiện tại, vì vậy tôi không nghĩ bạn cần cd. Trong trường hợp này f=readdir()[]sẽ còn ngắn hơn.
Dennis

6

MATLAB, 50 46 byte

e='.m';x=mfilename;movefile([x e],[flip(x) e])

Cảm ơn @Suever đã xóa 4 byte và để thử nghiệm!

Đã thử nghiệm trên OS X El Capitan và Debian Jessie, cả hai đều có phiên bản Matlab R2014a.

Trên Windows 'f'cần có cờ ( e='.m';x=mfilename;movefile([x e],[flip(x) e]),'f') để thay đổi tên tệp trong khi tệp đang được sử dụng.

Làm thế nào nó hoạt động

e='.m';                       % Store file extension '.m' in variable `e`
x=mfilename;                  % Get name of file being run, without the extension
movefile([x e],[flip(x) e])   % Move (rename) file. `flip` is used for reversing the
                              % name without extension. [...] is (string) concatenation

Bạn 'f'đang yêu cầu hệ điều hành nào?
Suever

@Suever Windows. Nó không cần thiết trên Mac?
Luis Mendo

Không cần thiết trên Mac của Linux.
Suever

@Suever Cảm ơn! Tắt 4 byte :-)
Luis Mendo

@Suever Bạn có thể chỉ ra hệ điều hành chính xác mà hệ thống này hoạt động không?
Luis Mendo

4

Ruby, 24 byte

File.rename$0,$0.reverse

Khá tự giải thích. ( $0là tên của tệp đang được thực thi.)

Chạy với ruby whatevermột thư mục làm việc của thư mục chứa tệp.


4

Mẻ, 109 byte

@echo off
set f=%0
set r=
:l
set r=%f:~0,1%%r%
set f=%f:~1%
if not .%f%==. goto l
ren %0.bat %r%.bat

Lưu ý 1: Các tệp hàng loạt phải kết thúc bằng .bat; giả định rằng tệp bó được thực thi bằng tên của nó mà không có phần mở rộng và .batkhông được đảo ngược. Ví dụ, reversesẽ cố gắng đổi tên reverse.batthành esrever.bat.
Lưu ý 2: CMD.EXElỗi sau khi đổi tên tệp bó. ( COMMAND.COMsẽ không, ngoại trừ việc nó không có khả năng thao tác chuỗi ở vị trí đầu tiên.)

Chỉnh sửa: Đã lưu 2 byte bằng cách sử dụng đảm bảo rằng tên tệp là chữ cái (dựa trên nhận xét của @ CᴏɴᴏʀO'Bʀɪᴇɴ).


3
1. TẠI SAO BẠN KHÔNG NÊN? 2. Tôi nghĩ bạn có thể tiết kiệm một byte bằng cách thực hiệnif ]%f% NEQ ] goto l
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ À đúng, tên tệp là chữ cái, vì vậy trên thực tế tôi có thể lưu 2 byte, nhưng cảm ơn vì gợi ý.
Neil

1
BẠN CẦN KHÔNG BẮT ĐẦU
mèo

4

C, 102 byte

main(c,v)char**v;{char*b=strdup(*v),*n=strrchr(*v,47),*t=strchr(b,0);for(;*++n;*--t=*n);rename(*v,b);}

Phá vỡ:

                            // No #include lines required (for GCC at least)
main(c,v)char**v;{          // K&R style function to save 2 bytes
    char*b=strdup(*v),      // Duplicate args[0] (script path)
        *n=strrchr(*v,47),  // Find last "/" in input
        *t=strchr(b,0);     // Go to end of output string
    for(;*++n;*--t=*n);     // Reverse input into output character-by-character
    rename(*v,b);           // Rename the file
}                           // Implicit return 0

Cuối cùng, một thử thách mà C không (khá vô vọng) không cạnh tranh!


Nếu chúng ta lấy "Bạn có thể giả định thư mục làm việc của vỏ sẽ là thư mục tập tin là trong" để có nghĩa là chương trình sẽ luôn luôn được gọi là ./myexecutable, chúng ta có thể đơn giản hóa *n=strrchr(*v,47)để *n=*v+1tiết kiệm 10 ký tự, nhưng điều này không phải là hoàn toàn hợp lệ ( nó có thể được gọi là ././myexecutable, ví dụ).


Ngoài ra nếu bạn muốn giữ phần mở rộng tệp (ví dụ: ".out"), bạn có thể thay đổi *t=strchr(b,0)thành *t=strrchr(b,46), tốn 2 byte. Không yêu cầu mặc dù.


Đẹp - Tôi chưa bao giờ nhìn xem renamesẽ làm gì nếu src == mệnh; có vẻ như bạn thỏa mãn các ràng buộc palindrom miễn phí.
Toby Speight

Lưu ý rằng điều này đòi hỏi một hệ thống tập tin trong đó codepoint 47 là dấu phân cách. Tôi nghĩ rằng điều này bao gồm POSIX (hoặc có cho phép EBCDIC /trong trường hợp góc không?)
Toby Speight

@TobySpeight yeah Tôi đã kiểm tra gnu.org/software/libc/manual/html_node/Renaming-Files.html để làm rõ, nhưng trường hợp gần nhất tôi tìm thấy là "Một trường hợp đặc biệt để đổi tên là khi tên cũ và tên mới là hai tên cho cùng một tệp Cách xử lý nhất quán trong trường hợp này là xóa tên cũ. Tuy nhiên, trong trường hợp này, POSIX yêu cầu đổi tên không làm gì và báo cáo thành công, điều này không nhất quán. Chúng tôi không biết hệ điều hành của bạn sẽ làm gì. ", Vì vậy tôi đoán là có một cơ hội bên ngoài nó sẽ chỉ xóa tệp trên các hệ thống không tuân thủ POSIX. Vì vậy, yeah, mã thực sự nên kiểm tra!
Dave

Tôi vừa kiểm tra linux.die.net/man/3/rename và nó xác nhận rằng Linux xử lý POSIX tuân thủ: "Nếu đối số cũ và đối số mới giải quyết cùng một tệp hiện có, đổi tên () sẽ trả về thành công hoạt động."
Dave

Tôi đã đi với trang quản lý Debian: "Nếu oldpathnewpathlà các liên kết cứng hiện có đề cập đến cùng một tệp, thì rename()không có gì và trả về trạng thái thành công" - nếu các chuỗi giống hệt nhau, chúng tham chiếu đến cùng một tệp.
Toby Speight

3

Vitsy + * sh, 15 byte

iG:`?r.iG' mr',

Giải trình

iG:`?r.iG' mr',
i               Push -1 to the stack. (this assumes that no arguments are passed)
 G              Get the use name of the class specified by the top item of the
                stack. (-1 refers to the origin class, so this class)
  :             Duplicate stack and jump to it.
   `            Read a file with the current stack as its name, replacing the stack
                with the file's contents.
    ?           Shift one stack to the right.
     r          Reverse the current stack.
      .         Write a file with the name specified by the top stack and the
                contents as the second-to-top stack.
       iG       Get the name of the current class again.
         ' mr'  Push 'rm ' to the stack.
              , Execute the current stack as a command.

Lưu ý rằng nội dung gửi này phải sử dụng phiên bản Vitsy không an toàn (không thể thực hiện trên Dùng thử trực tuyến!)


3

Perl 5, 18 byte

Một chút giống như Ruby (chạy perl nameofscript):

rename$0,reverse$0

Đưa một đường dẫn có thể vào tài khoản là xấu hơn (47 byte)

($a,$b)=$0=~/(.*\/)?(.*)/;rename$0,$a.reverse$b

1
Xin chào, và chào mừng đến với PPCG! Bài đăng đầu tiên tuyệt vời!
NoOneIsHãy

2

V , 29 26 byte

:se ri
izyw:!mv z "
dd

Vì cái này chứa các dấu vết không thể in được, đây là một bãi chứa hex:

00000000: 3a73 6520 7269 0a69 127a 1b79 773a 216d  :se ri.i.z.yw:!m
00000010: 7620 127a 2012 220a 6464                 v .z .".dd

Lưu ý: điều này sẽ không chạy trên v.tryitonline.net vì TIO không cho phép truy cập tệp.

Giải trình:

:se ri            "Turn on 'reverse mode' (all text is inserted backwards)
i<C-r>z<esc>      "Enter the path to the file in reverse
yw                "Yank a word. This first word is the name we will save the new file as

"Run an "mv" in the terminal with the contents of register 'z' (the path to the file)
"And the contents of register '"' (the word we yanked)
:!mv <C-r>z <C-r>"

dd                "Delete a line so that we don't have any text printed.

2

Python 3, 105 byte

import os;a=__file__.split('\\')[::-1][0].split('.');os.rename('.'.join(a),'.'.join([a[0][::-1],a[1]]))

-Alex.A đã xóa 1 byte.

-Digital Trauma cho tôi thấy os.rename () đã lấy đi 62 byte.

-muddyfish đã loại bỏ 7 byte.


Tôi nghĩ bạn có thể tiết kiệm một byte bằng cách xóa khoảng trắng sau dấu phẩy trongimport
Alex A.

import os,sys;f=sys.argv[0];os.rename(f,f[::-1])nên thực hiện thủ thuật cho 48 byte
Chấn thương kỹ thuật số

làm f [:: - 1] đảo ngược không chỉ tên tệp mà toàn bộ đường dẫn. Tuy nhiên, cảm ơn vì đã giới thiệu cho tôi tính năng os.rename ().
Magenta

@Magenta Đối với tôi, sys.argv[0]chỉ trả về tên tệp mà không có đường dẫn khi tập lệnh được chạy trực tiếp. Helka chỉ ra điều này là ổn
Chấn thương kỹ thuật số

@DigitalTrauma khi tôi tự chạy chương trình, sys.arg [0] đã trả về đường dẫn đầy đủ. Ill thêm một giải pháp thứ hai trong đó sys.argv [0] chỉ là tên tệp.
Magenta

2

PHP 84, 70, 54 byte

rename($f=__FILE__,strrev(basename($f,$e='.php')).$e);


EDIT: đã xóa 14 byte nhờ insertusernameherevào các bình luận
EDIT: đã xóa 16 byte nhờ Martijnvào các bình luận


2
Bạn có thể lấy nó xuống tới 70 byte : rename($f=__FILE__,__DIR__."/".strrev(pathinfo($f)[filename]).".php");.
insertusernamehere

Tuyệt vời !!! nhưng mã của bạn tốt hơn, wow bạn đã nhận được 31 byte
tttony

Bạn không thể làm cho nó tương đối? WOuld lưu 7 byte:rename($f=__FILE__,"./".strrev(pathinfo($f)[filename]).".php");
Martijn

hoặc thậm chí nhỏ hơn:rename(__FILE__,strrev(basename(__FILE__,'.php')).'.php');
Martijn

Mát mẻ! Thêm vars tôi nhận được bây giờ 54 byte
tttony

2

PowerShell, 39 byte

mi *(-join((ls).name)[-5..-999]+'.ps1')

Xin chào, và chào mừng đến với PPCG! Bài đăng đầu tiên rất hay!
Rɪᴋᴇʀ



1

Perl 6 ,  70   27 byte

Nếu nó cần để làm việc trong một thư mục làm việc khác, bạn sẽ cần một cái gì đó như thế này:

$_=$*PROGRAM;.rename: .basename.flip.IO.absolute: .absolute.IO.dirname

Vì thư mục làm việc sẽ là cùng thư mục với chương trình, nó có thể được đơn giản hóa thành:

$_=$*PROGRAM;.rename: .flip

Giải trình:

$_ = $*PROGRAM;  # IO::Path object

$_.rename:
    $_.basename
      .flip      # reverse characters
      .IO        # turn into an IO object (IO::Path)
      .absolute: # turn it into an absolute path Str in the following dir
        $_.absolute.IO.dirname

1

JavaScript (Nút), 108 104 68 byte

36 byte được lưu, nhờ có Downgoat!

Phiên bản Windows:

require("fs").rename(F=__filename,F.split(/.*\\|/).reverse().join``)

Phiên bản khác:

require("fs").rename(F=__filename,F.split(/.*\/|/).reverse().join``)

@Upgoat Tôi không cần, tôi không nghĩ. Tôi phù hợp jsở cuối filepath, trước một nhân vật. Điều này sẽ luôn luôn là một ..
Conor O'Brien

1

JavaScript ES6 (Node.js) 70 byte

Không có Regex Yay!

require("fs").rename(a=__filename,[...a].reverse().join``.split`/`[0])

Bất kỳ trợ giúp được đánh giá cao


1

PowerShell v4 +, 68 byte

$a,$b=($c=(ls).Name)-split'\.';mv $c "$(-join($a[$a.length..0])).$b"

Chỉ hoạt động vì tập lệnh được đảm bảo nằm trong một thư mục. Thực hiện một ls(bí danh cho Get-ChildItem) và lấy .Name(các) đối tượng kết quả. Chúng tôi lưu trữ nó trong $cvà sau -splitđó vào khoảng thời gian theo nghĩa đen để có được tên tệp và phần mở rộng, và lưu trữ chúng trong $a$b, tương ứng.

Tiếp theo là lệnh mv(bí danh cho Move-Item), nơi chúng ta đang di chuyển $cđến $a(đảo ngược) .$b.

Thí dụ

PS C:\Tools\Scripts\golfing\reverse> ls

    Directory: C:\Tools\Scripts\golfing\reverse

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         6/13/2016   7:58 AM         88 reverse.ps1

PS C:\Tools\Scripts\golfing\reverse> .\reverse.ps1

PS C:\Tools\Scripts\golfing\reverse> ls

    Directory: C:\Tools\Scripts\golfing\reverse

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         6/13/2016   7:58 AM         88 esrever.ps1

1

Python (2.7 hoặc 3.4+), 61 49 byte

Tôi tin rằng điều này gần với giải pháp Python tối ưu:

import os;a=__file__;os.rename(a,a[-4::-1]+".py")

Lấy cảm hứng từ s4b3r6câu trả lời của mình, nhưng sử dụng cắt danh sách thay vì đảo ngược và lưu __file__vào một biến để lưu byte khi sử dụng hai lần.

Lưu ý: Điều này giả định rằng tên tệp luôn luôn *.py. Một giải pháp chung chung hơn một chút có thể xử lý bất kỳ phần mở rộng tệp hai ký tự nào sẽ được sử dụng a[-3:]để thay thế ".py", với chi phí thêm 1 byte.

Cập nhật: Đã lưu 12 byte bằng cách sử dụng thủ thuật cắt danh sách a[-4::-1]để xóa phần mở rộng tệp, thay vì tách và sau đó đảo ngược với a.split(".")[0][::-1].


1

Powershell, 112 byte

Tôi sẽ không đánh bại các cmds unix, chỉ cần thêm hai xu cho vui :-)

gci * | % { $n=($_.basename[-1..-(($_.basename).length)] -join “”)+$_.Extension; mv -Path $_.Fullname -Dest $n }

Chào mừng đến với PPCG! Chúng tôi yêu cầu câu trả lời hiển thị điểm số của họ, vì vậy tôi đã chỉnh sửa nó cho bạn. Ngoài ra, bạn có thể định dạng mã của mình bằng cách tô sáng mã đó và chọn nút trông giống dấu ngoặc {}hoặc bằng cách thêm 4 khoảng trắng trước mã của bạn.
FryAmTheEggman

0

PowerShell, 50 byte

mv *(-join($f=(ls).BaseName)[$f.Length..0]+'.ps1')

Chỉ có một tệp, vì vậy mv *ký tự đại diện sẽ chỉ có một kết quả. Tên đích (ls).basenameliệt kê tất cả các tệp (bí danh cho 'dir'), gọi thuộc tính BaseName - và vì chỉ có một tệp, PowerShell sẽ giải nén mảng 1 mục thành một chuỗi. Lưu tên tệp đó vào $f, sau đó lập chỉ mục cho nó đếm ngược và -joincác ký tự đảo ngược sao lưu thành một chuỗi. Thêm .ps1hậu tố bắt buộc .


0

Tự động, 45 byte

$a=@ScriptName
FileMove($a,StringReverse($a))

0

Python 2.7, 68 byte

nhập os; a = __ tệp __; os.rename (a, a.split ("\\") [- 1] [: - 3] [:: - 1] + ". py")

Đây có lẽ là điều tốt nhất tôi có thể nhận được nó. Tôi chỉ chứng minh mình sai.


0

Python (2 & 3), 88 78 byte

import os;os.rename(__file__,''.join(reversed(__file__.split(".")[0]))+".py"))

Khai thác thực tế là tên tệp được đưa ra bởi sys.argv (vì thư mục làm việc là thư mục chứa tệp) và sử dụng os.rename. Khó chịu, đảo ngược trả về một iterator, vì vậy chúng ta phải sử dụng tham gia.

Chỉnh sửa: Đã lưu 10 byte bằng cách sử dụng __file__ thay vì sys.argv [0], như được đề xuất bởi @muddyfish cho @DigitalTrauma.



0

Visual Basic Script, 44 byte

WScript.Echo(StrReverse(WScript.ScriptName))

Ví dụ đầu ra cho tệp được gọi reverse.vbs(Chạy với cscript):

sbv.esrever


0

SmileBASIC 60 byte

P$=PRGNAME$()FOR I=1-LEN(P$)TO.Q$=Q$+P$[-I]NEXT
RENAME P$,Q$

Thay thế:

P$=PRGNAME$()T$=P$*1WHILE""<T$Q$=Q$+POP(T$)WEND
RENAME P$,Q$
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.