จบแท็บกับสงครามอวกาศ


24

จบแท็บกับสงครามอวกาศ

ดังนั้นจึงมีการถกเถียงกันอย่างมากว่าจะใช้แท็บหรือช่องว่างเพื่อเยื้อง / จัดรูปแบบโค้ด คุณสามารถช่วยมหาวิทยาลัยตัดสินข้อพิพาทโดยไปที่วิธีการจัดรูปแบบที่ไม่ซ้ำกัน อย่างบ้าคลั่งอย่างไม่น่าเชื่อ


งานของคุณคือการเขียนโปรแกรมหรือฟังก์ชั่นเต็มรูปแบบซึ่งขยายแท็บทั้งหมดออกเป็นสี่ช่องว่าง จากนั้นแทนที่ช่องว่างนำหน้าด้วย n ช่องว่างด้วย "/ (n - สองดาวที่นี่) /" คุณจะได้รับอินพุตมากกว่าหลายบรรทัดในรูปแบบที่เหมาะสม (อาเรย์สตริงเดี่ยวของสตริงสำหรับแต่ละบรรทัดใหม่อาเรย์เรียงเป็นแนว ฯลฯ )

การป้อนข้อมูลตัวอย่างที่ถูกขโมยลงคอ โปรดทราบว่าเนื่องจากแท็บขยายโดยอัตโนมัติเป็นสี่ช่องว่างใน SE ฉันจึงแสดงว่าเป็นอักขระ "^" แต่คุณต้องจัดการกับแท็บ (codepoint 0x09) เช่นกัน อักขระ "^" ทั้งหมดแสดงถึงตาราง

Calculate the value 256 and test if it's zero
If the interpreter errors on overflow this is where it'll happen
++++++++[>++++++++<-]>[<++++>-]
+<[>-<
    Not zero so multiply by 256 again to get 65536
    [>++++<-]>[<++++++++>-]<[>++++++++<-]
    +>[>
        # Print "32"
        ++++++++++[>+++++<-]>+.-.[-]<
    <[-]<->] <[>>
        # Print "16"
        +++++++[>+++++++<-]>.+++++.[-]<
<<-]] >[>
    # Print "8"
    ++++++++[>+++++++<-]>.[-]<
<-]<
# Print " bit cells\n"
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<.
>>.++.+++++++..<-.>>-
Clean up used cells.
[[-]<]l
^this is preceded by a tab
^^two tabs
^^^three tabs etcetera! 

ตัวอย่างผลลัพธ์

Calculate the value 256 and test if it's zero
If the interpreter errors on overflow this is where it'll happen
++++++++[>++++++++<-]>[<++++>-]
+<[>-<
/**/Not zero so multiply by 256 again to get 65536
/**/[>++++<-]>[<++++++++>-]<[>++++++++<-]
/**/+>[>
/******/# Print "32"
/******/++++++++++[>+++++<-]>+.-.[-]<
/**/<[-]<->] <[>>
/******/# Print "16"
/******/+++++++[>+++++++<-]>.+++++.[-]<
<<-]] >[>
/**/# Print "8"
/**/++++++++[>+++++++<-]>.[-]<
<-]<
# Print " bit cells\n"
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<.
>>.++.+++++++..<-.>>-
Clean up used cells.
[[-]<]l
/**/this is preceded by a tab
/******/two tabs
/**********/three tabs etcetera! 

เนื่องจากมหาวิทยาลัยต้องการพื้นที่ในการดาวน์โหลดทั้ง Vim และ Emacs คุณจึงได้รับอนุญาตให้ใช้พื้นที่เก็บข้อมูลเพียงเล็กน้อยสำหรับโค้ดของคุณ ดังนั้นนี่คือและรหัสที่สั้นที่สุดชนะ คุณอาจสมมติว่าอินพุตมีรูปแบบที่ดีและบรรทัดที่มีช่องว่างน้อยกว่าสี่ช่อง (หลังจากแทนที่แท็บ) อาจส่งผลให้เกิดพฤติกรรมที่ไม่ได้กำหนด

คำปฏิเสธ

กลยุทธ์การจัดรูปแบบ "ยอดเยี่ยม" นี้ได้รับความอนุเคราะห์จาก Geobits และทำซ้ำโดยได้รับอนุญาต ไม่มีโปรแกรมเมอร์คนใดได้รับอันตรายในระหว่างการสร้างความท้าทายนี้


1
แท็บจะเกิดขึ้นเฉพาะที่จุดเริ่มต้นของบรรทัด (เช่นเป็นการเยื้อง) หรือไม่ บรรทัดมีการเยื้องผสม (แท็บ + ช่องว่าง) หรือไม่
ลินน์

20
คนโปรดส่งคำตอบที่เขียนในช่องว่าง
GuitarPicker

2
เราควรพิจารณาบรรทัดที่ขึ้นต้นด้วย/*หรืออาจสันนิษฐานได้ว่าไม่ใช่ แฟ้มแหล่ง c ++ จะได้รับการทดสอบที่ดีกว่าเพราะหลายความคิดเห็นของตน/* */อาจจะทำลายคำตอบบางอย่างที่เข้ามาแทนที่แรกและครั้งสุดท้ายของช่องว่างนำที่มีแล้วดำเนินการต่อไปเพื่อเติมเต็มช่องว่างด้วย/ *
seshoumara

1
สงครามสิ้นสุดลงแล้ว: medium.com/@hoffa/… (เว้นแต่คุณจะตั้งโปรแกรมใน C, ชัด ๆ )
บีกเกอร์

1
@RohanJhunjhunwala ดังนั้นตอนนี้ฉันถามคำถามแรกของฉันอีกครั้งเพราะมันไม่เกี่ยวกับรหัสที่คอมไพล์ได้ ลองนึกภาพ/* */รหัส C ++ ที่เหมือนกันแต่คราวนี้ที่จุดเริ่มต้นของบรรทัด ตามสเป็คของคุณควรทิ้งไว้ตามที่เป็น นี่คือกับดักเป็นและเห็นคำตอบที่ผิดอยู่แล้วว่า regex เช่นพูด/\** /ที่ใช้ในการเติมเต็มช่องว่างระหว่าง // /***/กับดอกจันจะเปิดสายเข้า /*//*/ผมเคยเห็นการแปลงนี้เป็นอย่างดี ฉันถือว่าทั้งคู่ไม่ถูกต้อง
seshoumara

คำตอบ:


2

V , 21 , 20 ไบต์

Íô/    
Î^hr/hv0r*r/

ลองออนไลน์!

นี่เป็นเพียงพอร์ตโดยตรงของคำตอบกลุ่มของฉัน ความแตกต่างที่โดดเด่น:

  • Íคำสั่ง (แทนทั่วโลก) เติมโดยอัตโนมัติใน/gธงซึ่งจะช่วยประหยัดไบต์ที่สอง

  • ô เหมือนกันกับ \t

  • Îเป็นตัวช่วยจำสำหรับ:%normและยังเติมในช่องว่างที่จำเป็นระหว่าง:%normและชุดของการกดแป้น

  • มีการเพิ่มการรับคืนส่วนท้ายที่ส่วนท้ายโดยนัย


27

เป็นกลุ่ม, 37, 34, 33, 32 ไบต์

:%s/\t/    /g|%norm ^hr/hv0r*r/

ลองออนไลน์!

โปรดทราบว่าการทำเช่นนี้จะต้องใช้การส่งคืนส่วนท้าย (ป้อน) เป็นกลุ่มแม้ว่าจะไม่ได้อยู่ในล่ามออนไลน์

วิธีนี้ใช้ล่าม V เพราะเข้ากันได้ย้อนหลัง ทางออกที่ตรงไปตรงมามาก

นี่คือ gif ที่ช่วยให้คุณเห็นการแก้ปัญหาที่เกิดขึ้นในเวลาจริง นี่ใช้รุ่นที่เก่ากว่าเล็กน้อยและฉันได้เพิ่มการกดแป้นพิเศษบางอย่างเพื่อให้ทำงานช้าลงเพื่อให้คุณเห็นสิ่งที่เกิดขึ้น:

enter image description here

และนี่คือคำอธิบายวิธีการทำงาน:

:%s/\t/    /g           "Replace every tab with 4 spaces
|                       "AND
%norm                   "On every line:
      ^                 "  Move to the first non-whitespace char
       h                "  Move one character to the left. If there is none, the command will end here.
         r/             "  Replace it with a slash
           h            "  Move to the left
            v0          "  Visually select everything until the first column
              r*        "  Replace this selection with asterisks
                r/      "  Replace the first character with a slash

ฉันจะ +1 เพื่อใช้gแต่คุณก็แก้ไขไม่ได้ใช้ g: / +1 ต่อไป: D
Downgoat

@downgoat ฮ่าฮ่าขอบคุณ! จริง ๆ แล้วฉันเป็นรุ่น prouder โดยไม่ได้:gเพราะมันละเมิดคุณสมบัติที่รู้จักกันน้อย: normคำสั่งจะถูกยกเลิกหาก^F<space>ล้มเหลว ดังนั้น:%norm ^F<space>fooโดยพื้นฐานแล้วสิ่งเดียวกับ:g/^ /norm fooความสนุกในกลุ่มแฮ็ค : D
DJMcMayhem

ฉันคิดว่า ^ F คุ้นเคยกับการโพสต์หน้าจอ มันมีพฤติกรรมที่แตกต่างกันภายในnorm?
Downgoat

1
@downgoat ฮ่าฮ่าไม่มัน^Fไม่ใช่<C-f>สัญญลักษณ์Silly Vim ในกรณีนี้^ให้ข้ามไปยังอักขระแรกที่ไม่ใช่ช่องว่างและF<space>ค้นหาช่องว่างหลังเคอร์เซอร์
DJMcMayhem

ohhh, ที่ทำให้รู้สึกมากขึ้นในขณะนี้> _>
Downgoat

11

Perl, 41 ไบต์

s,␉,    ,g;s,^  ( +),/@{[$1=~y| |*|r]}/,

วิ่งด้วย-pธงเช่นนี้

perl -pe 's,␉,    ,g;s,^  ( +),/@{[$1=~y| |*|r]}/,'
#     ↑   └───────────────────┬───────────────────┘
#     1 byte               40 bytes

แทนที่ด้วยแท็บ (ใน Bash ลองพิมพ์Control-V Tab)


1
วิธีperlแทนที่ backreference นั้นตรงจุดฉันก็หวังsedเช่นกัน
seshoumara

7

เนยแข็งชนิดหนึ่ง , 60 57 56 ไบต์

บันทึกแล้ว 3 ไบต์ขอบคุณ @Conor O'Brien

@.sub(/\t/g," "*4).sub(/^ +/gm,i->"/"+"*"*(i.len-2)+"/")

ฉันหวังว่า Cheddar จะมีการจัดรูปแบบสตริงที่ดีกว่า

ลองออนไลน์!

คำอธิบาย

นี่คือฟังก์ชั่น @เป็นคุณสมบัติที่แสดงหน้าที่ (เช่น ruby &:) ให้คุณทำสิ่งต่าง ๆ เช่น: `ar.map (@. head (-1))

@                      // Input
 .sub( /\t/g, " "*4)   // Replace tabs with four spaces
 .sub(
   /^ +/gm,            // Regex matches leading spaces
   i ->                // i is the matched leading spaces
     "/"+              // The / at the beginning
     "*"*(i.len-2)+    // Repeat *s i-2 times
     "/"                // The / at the end
 )

หากคุณไม่คุ้นเคยกับ regex:

/^ +/gm

โดยทั่วไปจะจับคู่หนึ่ง+ช่องว่างหรือมากกว่า ( ) ที่จุดเริ่มต้น ( ^) ของทุกgบรรทัด ( m)


แท็บตัวอักษรทำงานใน regexes cheddar ได้อย่างไร ยัง/^ +/พอเพียงเป็น regex เนื่องจากเราสามารถสรุปได้ว่าช่องว่างนำหน้าจะมีความยาวอย่างน้อย 4 ตัว
Conor O'Brien

@ ConorO'Brien ฉันเชื่อว่าพวกเขาทำ แต่ฉันไม่ได้ทดสอบ
Downgoat

แท็บควรถูกแทนที่ก่อนการแปลง
Conor O'Brien

@ ConorO'Brien โอ้> _> ฉันมีวิธีนั้น แต่เดิมแล้วฉันเปลี่ยนมัน
Downgoat

6

Mathematica, 97 ไบต์

a=StringReplace;a[a[#,"\t"->"    "],StartOfLine~~b:" "..:>"/"<>Table["*",StringLength@b-2]<>"/"]&

ฟังก์ชั่นไม่ระบุชื่อ รับสตริงเป็นอินพุตและส่งคืนสตริงเป็นเอาต์พุต



4

Java 210 207 ไบต์

นี่คือโซลูชันอ้างอิงที่ใช้งานอย่างไร้เดียงสา

void a(String[]a){for(String s:a){s=s.replaceAll("\t", "    ");String x,y="";int j,i=s.length()-(x=s.replaceAll("^\\s+", "")).length();if(i>3){y="/";for(j=0;j++<i-1;)y+="*";y+="/";}System.out.println(y+x);}}

6
เป็นกลุ่ม: 37 bytes, Cheddar: 65 bytes, JavaScript: 75 bytes, จากนั้นมี Java ที่ 210 bytes: P ทำไมฉันไม่แปลกใจเลย
Downgoat

1
รหัสย่อที่กระชับมากใน java: P
Rohan Jhunjhunwala

คุณสามารถเปลี่ยนสุดท้ายสำหรับวงที่จะบันทึก 1 for(int j=0;++j<i-1;)ไบต์: นอกจากนี้คุณยังสามารถลบint ก่อนjและวางไว้หลังจากที่ int อยู่แล้ว:int i=s.length()-(x=s.replaceAll("^\\s+", "")).length(),j;
เควิน Cruijssen

แลมบ์ดาไม่สามารถโกนไบต์ด้วย (a) -> {... } ใช่ไหม
bunyaCloven

อย่างน้อยก็ยังสามารถอ่านได้และไม่ต้องการความคิดเห็นเพิ่มเติม: o)
René

3

JavaScript ES6, 75 ไบต์

s=>s.replace(/\t/g,"    ").replace(/^ +/gm,k=>`/${"*".repeat(k.length-2)}/`)

แทนที่\tด้วยแท็บตัวอักษรในรหัสของคุณ


3

Java, 185 184 167 152 ไบต์

S->S.map(s->{s=s.replace("\t","    ");String t=s.replaceAll("^ +","");int n=s.length()-t.length();if(n>3){s="/";for(;n-->2;)s+="*";s+="/"+t;}return s;})

เนื่องจากนิยามของสตริงอาเรย์ที่หลวมมากในโพสต์เริ่มต้นฉันได้ใช้Stream<String>ซึ่งทำให้สามารถประหยัดไบต์ได้

ฉันใช้เทคนิคที่แตกต่างจาก RI เพื่อให้บรรลุเป้าหมายเดียวกัน อัลกอริทึมนั้นค่อนข้างเหมือนกัน

การทดสอบและ ungolfed :

import java.util.Arrays;
import java.util.stream.Stream;

public class Main {

  public static void main(String[] args) {
    StringStreamTransformer sst = lines -> lines.map(line -> {
      line = line.replace("\t","    ");
      String trimmed = line.replaceAll("^ +", "");
      int startingSpaces = line.length() - trimmed.length();
      if (startingSpaces > 3) {
        line = "/";
        for(;startingSpaces > 2; startingSpaces--) {
          line += "*";
        }
        line += "/" + trimmed;
      }
      return line;
    });


    Stream<String> lines = Arrays.stream(new String[]{
      "lots of spaces and tabs after\t\t    \t\t         \t\t\t\t\t",
      "no space",
      " 1 space",
      "  2 spaces",
      "   3 spaces",
      "    4 spaces",
      "     5 spaces",
      "      6 spaces",
      "       7 spaces",
      "        8 spaces",
      "\t1 tab",
      "\t\t2 tabs",
      "\t\t\t3 tabs"
    });
    sst.map(lines).map(s -> s.replace(" ", ".").replace("\t","-")).forEach(System.out::println);


  }
}

2

เรติน่า 25 ไบต์

\tควรจะถูกแทนที่ด้วยตัวแท็บจริง (0x09)

\t
4$* 
%`^  ( +)
/$.1$**/

ลองออนไลน์!

คำอธิบาย

\t
4$* 

แทนที่แต่ละแท็บด้วยช่องว่างสี่ช่อง

%`^  ( +)
/$.1$**/

แปลงแต่ละบรรทัดแยก ( %) โดยการจับคู่2+Nช่องว่างที่จุดเริ่มต้นของบรรทัดและแทนที่ด้วย/.../ที่...เป็นสำเนาN*



2

SED (56 + 1 สำหรับ -r) 57

s/⇥/    /g;tr;:r;s,^ ( *) ,/\1/,;T;:l;s,^(/\**) ,\1*,;tl

แท็บอยู่ที่ไหน
1. แทนที่แท็บด้วยช่องว่าง
2. /แทนที่แรกและครั้งสุดท้ายพื้นที่ชั้นนำที่มี
3. แทนที่ช่องว่างแรกหลังจาก/และ 0+ *ด้วย*จนกว่าจะไม่มีการแข่งขัน


เนื่องจากมีการระบุ sed จึงไม่จำเป็นต้องใส่เครื่องหมายอัญประกาศเดี่ยวรอบ ๆ โค้ดเหมือนกับการลบ -r '' ออกจากคำตอบ sed อื่น ๆ ของคุณเพราะคุณสามารถพิจารณาสคริปต์ว่าเก็บไว้ในไฟล์ต้นฉบับที่คุณรันด้วย-fหรือไม่ การตั้งค่าสถานะพิเศษใด ๆ ที่ใช้เช่น n หรือ r ควรนับเป็นหนึ่งไบต์ต่อครั้ง ดังนั้นที่นี่คุณบันทึก 2 ไบต์
seshoumara

นั่นคือสิ่งที่ฉันคิด แต่ฉันต้องการ ขอบคุณ
Riley

;หลังจากทีคำสั่งไม่จำเป็นต้องมีอย่างใดอย่างหนึ่ง สำหรับโค้ดนั้นคุณต้องมี ^ ที่จุดเริ่มต้นของsคำสั่งที่สามมิฉะนั้นอินพุตเช่นนี้ "3/5" จะเปลี่ยนเป็น "3 / * 5" ในsคำสั่งแรกคุณมีแท็บที่นั่นจริง ๆ แต่มันไม่ถูกแสดงอย่างถูกต้องและทำให้เข้าใจผิดดังนั้นให้ใช้ \ t หรือระบุหลังจาก char นั้นเป็นแท็บ
seshoumara

@seshoumara ขอบคุณฉันพยายามโพสต์จากโทรศัพท์ของฉัน ... มันไม่ใช่สิ่งที่ง่ายที่สุดที่จะทำ
Riley

ฉันคิดว่าฉันใช้เวลาแก้ไขคำตอบนี้มากกว่าคำอื่น ๆ ทั้งหมดรวมกัน ขอบคุณสำหรับความช่วยเหลือ!
Riley

1

มหาวิทยาลัยควรพิจารณาอนุญาตให้เพิ่มพื้นที่สำหรับโปรแกรมใน Emacs Lisp (หรือเป็นค่าเริ่มต้นtabifyและuntabifyคนเดียว) เนื่องจากพวกเขาได้รับ verbose มากกว่า Java นอกจากนี้ควรให้ความสำคัญกับนักเรียน (หรือครู) ที่มีขนาดตัวตนน้อยกว่าสี่คนหรือผู้ที่เกิดรหัสในภาษาที่ไม่เหมือนกับ C

วิธีแก้ไขปัญหาต่อไปนี้มี206 ไบต์

(lambda (b e)(let((tab-width 4))(untabify b e)(goto-char b)(while(re-search-forward"^ +"e t)(replace-match(format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2)))))))))

สมมติว่าtab-widthไม่จำเป็นต้องตั้งค่าอย่างชัดเจนเราสามารถบันทึกได้ 20 รายการ

(lambda(b e)(untabify b e)(goto-char b)(while(re-search-forward"^ +"e t)(replace-match(format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2))))))))

และรุ่นที่ไม่ดีจะมีลักษณะเช่นนี้

(defun end-tab-war (beg end)
  (let ((tab-width 4))
    (untabify beg end)
    (goto-char beg)
    (while (re-search-forward "^ +" end t)
      (replace-match
       (format
        "/%s/"
        (apply 'concat
               (mapcar (lambda(x) "*")
                       (number-sequence 1
                                        (- (length (match-string 0))
                                           2)))))))))

เราเริ่มuntabifyภาคก่อนที่จะกระโดดเพื่อเริ่มต้น จากนั้นในขณะที่เราเห็นช่องว่างที่จุดเริ่มต้นของบรรทัดเราแทนที่ด้วยความคิดเห็นที่ตราบเท่าที่ช่องว่างดังกล่าว ความคิดเห็นที่จะแทรกถูกสร้างขึ้นโดย

 (format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2)))))

ซึ่งตัวเองใช้เวลาถึง 97 ไบต์ โซลูชันที่สั้นลงเพื่อคัดลอกบางสตริง n ครั้งเป็นที่นิยมอย่างมาก


1

ทับทิม, 52 47 + 1 (p flag) = 48 ไบต์

แก้ไข : บันทึกทั้ง 5 ไบต์ด้วย Value Ink

ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'

1
คุณสามารถใช้pแฟล็กเพื่อใช้ประโยชน์จากข้อเท็จจริงที่ว่า (g) ย่อยแก้ไข$_และเปลี่ยนแปลงค่าที่พิมพ์หรือไม่? ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'
หมึกมูลค่า

ขอบคุณฉันไม่ทราบว่า(g)subหากไม่มีการระเบิดสามารถแก้ไขได้$_ที่นี่
michau

1

GNU sed, 66 64 + 1 (แฟล็ก r) = 65 ไบต์

แก้ไข: 1 ไบต์น้อยลงขอบคุณคำแนะนำของRiley

s/\t/    /g
s,^ ( *) ,/\1\n,
:
s,^(/\**) ( *\n),\1*\2,
t
s,\n,/,

รัน: sed -rf formatter.sed input_file

เหตุผลสำหรับการแยกกับการให้\nพื้นที่ชั้นนำจากส่วนที่เหลือของข้อความในบรรทัดว่าเป็นเพราะมิฉะนั้น c ++ บรรทัดที่เริ่มต้นด้วยการแสดงความคิดเห็นเช่นนี้/* */จะกลายเป็น/*****/เป็นเส้นที่เรียบง่าย 4 ชอบหรือแม้กระทั่งs,^(/\**) ,\1*, s,^(/\**) ( */),\1*\2,เนื่องจาก sed ดำเนินการสคริปต์สำหรับแต่ละบรรทัดอินพุตจึงไม่\nถูกนำมาใช้ในพื้นที่รูปแบบในการอ่าน


คุณสามารถบันทึกไบต์โดยไม่ได้วางในการปิดจนกว่าคุณจะเปลี่ยน/ \nที่ช่วยให้คุณไม่ต้องจับคู่ในบรรทัดที่ 4
Riley

@Riley ดีจับ อัปเดตรหัส
seshoumara

คุณสามารถบันทึกอื่นโดยแทนที่\tด้วยอักขระแท็บ
Riley

@Riley นั่นเป็นความจริง แต่เนื่องจากมันจะไม่ถูกพิมพ์เป็นแท็บที่นี่ฉันมีข้อสงสัย ฉันจะเก็บเรื่องนี้ไว้ในใจสำหรับคำตอบในอนาคตด้วยการนับไบต์แข่งขันมากขึ้น
seshoumara
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.