ความบ้าคลั่งกระจกวิเศษ


22

บทนำ

ฉันมีห้องเต็มไปด้วยกระจกวิเศษ พวกเขาเป็นสิ่งประดิษฐ์ลึกลับที่สามารถทำซ้ำรายการใด ๆ ยกเว้นกระจกวิเศษอื่น รายการรุ่นที่ซ้ำกันจะปรากฏที่อีกด้านหนึ่งของมิเรอร์ในระยะทางเดียวกัน อย่างไรก็ตามหากมีกระจกวิเศษอีกอันอยู่ข้างใดข้างหนึ่งระหว่างกระจกที่ทำซ้ำและสิ่งของ (ทั้งแบบดั้งเดิมหรือแบบซ้ำ) จะไม่เกิดการทำซ้ำ รายการต้นฉบับสามารถเป็นไปทางซ้ายหรือทางขวาของกระจกเงาและรายการที่ซ้ำกันจะปรากฏที่อีกด้านหนึ่ง อีกทั้งสามารถทำสำเนารายการที่ซ้ำกันด้วยมิร์เรอร์อื่น รายการไม่เคยบล็อกการทำซ้ำของรายการอื่น ๆ (ยกเว้นโดยการอยู่ในตำแหน่งที่ต้องการซ้ำโดยตรง)

อินพุต

ข้อมูลที่คุณป้อนเป็นสตริงที่ประกอบด้วยอักขระ.#|ซึ่งแสดงถึงพื้นที่ว่างรายการและกระจกวิเศษ จะมีกระจกวิเศษอย่างน้อยหนึ่งตัวในอินพุต

เอาท์พุต

ผลลัพธ์ของคุณจะเป็นอีกสายหนึ่งที่กระจกวิเศษแต่ละอันจะทำซ้ำทุกรายการที่ทำได้ตามกฎข้างต้น คุณสามารถสันนิษฐานได้ว่าจะมีพื้นที่ว่างเสมอในจุดที่มีรายการที่ซ้ำกันปรากฏขึ้น (ดังนั้นพวกเขาจะไม่ออกนอกขอบเขต)

ตัวอย่าง

พิจารณาสตริงการป้อนข้อมูล

.#.|.....|......#
 A B     C      D

ที่ซึ่งเราได้ทำเครื่องหมายบางตำแหน่งเพื่อความชัดเจน มิเรอร์BทำสำเนารายการAซึ่งสิ้นสุดไปทางขวา:

.#.|.#...|......#
 A B     C      D

มิร์เรอร์Cทำซ้ำรายการใหม่:

.#.|.#...|...#..#
 A B     C      D

มิเรอร์Cไม่สามารถทำซ้ำรายการAเนื่องจากมิเรอร์Bอยู่ในทาง นอกจากนี้ยังไม่สามารถทำซ้ำรายการDเนื่องจากมิเรอร์Bอยู่ในอีกด้านหนึ่ง ในทำนองเดียวกันมิเรอร์Bไม่สามารถทำซ้ำรายการDหรือทำซ้ำที่อยู่ติดกับมันเนื่องจากมิเรอร์Cอยู่ในทางดังนั้นนี่คือผลลัพธ์ที่ถูกต้อง

สำหรับตัวอย่างอื่นให้พิจารณาอินพุต

.##..#...|#..##...|..##....#.
 AB  C   DE  FG   H  IJ    K

มิเรอร์Dสามารถทำซ้ำAและBไปทางขวาEและGไปทางซ้าย CและFซ้ำซ้อนกันอยู่แล้ว สตริงกลายเป็น

.##.##..#|#..##.##|..##....#.
 AB  C   DE  FG   H  IJ    K

กระจกHสามารถทำซ้ำE, Fและรายการที่ซ้ำกันของAและBไปทางขวาและIไปทางซ้าย GและJมีการซ้ำซ้อนกันอยู่แล้วและมิเรอร์Dก็เป็นแบบKนั้น ตอนนี้เรามี

.##.##..#|#..#####|#####..##.
 AB  C   DE  FG   H  IJ    K

ในที่สุดกระจกDสามารถทำซ้ำสิ่งที่ซ้ำกันIทางซ้าย เราจบลงด้วย

.#####..#|#..#####|#####..##.
 AB  C   DE  FG   H  IJ    K

กฎและการให้คะแนน

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

กรณีทดสอบ

"|" -> "|"
"..|.." -> "..|.."
".#.|..." -> ".#.|.#."
"..#|.#." -> ".##|##."
".#..|....|.." -> ".#..|..#.|.#"
".|..|.#....." -> "#|#.|.#....."
"...|.#...|....#" -> ".##|##...|...##"
"......#|......." -> "......#|#......"
".#.|.....|......#" -> ".#.|.#...|...#..#"
".......|...#.##|...." -> "##.#...|...#.##|##.#"
"...#..||.......#..#...#" -> "...#..||.......#..#...#"
".##|.#....||#||......#|.#" -> ".##|##....||#||.....##|##"
".##..#...|#..##...|..##....#." -> ".#####..#|#..#####|#####..##."
".#|...||...|#...|..##...|#...." -> ".#|#..||.##|##..|..##..#|#..##"
"....#.|...#.|..|.|.....|..#......" -> "..#.#.|.#.#.|.#|#|#.#..|..#.#...."
"..|....|.....#.|.....|...|.#.|..|.|...#......" -> ".#|#...|...#.#.|.#.#.|.#.|.#.|.#|#|#..#......"

เราสามารถนำอาเรย์ของอักขระเป็นอินพุตและ / หรือเอาต์พุตได้หรือไม่?
Conor O'Brien

@ ConorO'Brien No ยกเว้นว่าเป็นตัวแทนของสตริงในภาษาของคุณ
Zgarb

คำตอบ:


10

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

+`([#.])(([#.])*\|(?>(?<-3>[#.])*))(?!\1)[#.]
#$2#

ลองออนไลน์! (บรรทัดแรกเปิดใช้งานชุดทดสอบที่แยกบรรทัดด้วยฟีด)

ฉันเดาว่านี่เป็นสิ่งที่ตรงกันข้ามกับการส่ง (ไม่มี regex)

คำอธิบาย

นี่เป็นเพียงการทดแทน regex ซึ่งถูกนำไปใช้ซ้ำ ๆ ( +) จนกระทั่งสตริงหยุดการเปลี่ยนแปลง ฉันใช้ความสมดุลของกลุ่มเพื่อให้แน่ใจว่าสองตำแหน่งสะท้อนอยู่ในระยะเดียวจากกระจกที่กำหนด (backreferences จะไม่ทำตั้งแต่สตริงที่ถูกต้องในทั้งสองด้านของ|อาจจะแตกต่างกัน)

([#.])            # Match and capture a non-mirror cell.
(                 # This will match and capture everything up to its corresponding
                  # cell so that we can write it back in the substitution.
  ([#.])*         #   Match zero or more non-mirror cells and push each one onto
                  #   group 3. This counts the distance from our first match to
                  #   the mirror.
  \|              #   Match the mirror.
  (?>             #   Atomic group to prevent backtracking.
    (?<-3>[#.])*  #     Match non-mirror while popping from group 3.
  )               #   There are three reasons why the previous repetition
                  #   might stop:
                  #   - Group 3 was exhausted. That's good, the next position
                  #     corresponds to the first character we matched.
                  #   - We've reached the end of the string. That's fine,
                  #     the last part of the regex will cause the match to fail.
                  #   - We've hit another mirror. That's also fine, because
                  #     the last part of the regex will still fail.
)
(?!\1)            # Make sure that the next character isn't the same as the first
                  # one. We're looking for .|# or #|., not for #|# or .|.
[#.]              # Match the last non-mirror character.

นี้จะถูกแทนที่ด้วยซึ่งก็แทนที่ทั้งตัวอักษรตัวแรกและครั้งสุดท้ายของการแข่งขันด้วย#$2##


9

Perl, 49 ไบต์

ให้เครดิตแก่@Martin Enderสำหรับผู้ที่แนะนำ regex นี้ให้สั้นกว่าของฉัน 15 ไบต์

47 ไบต์ของรหัส + -plธง

s/([.#])(\||[^|](?2)[^|])(?!\1)[^|]/#$2#/&&redo

วิธีเรียกใช้:

perl -plE 's/([.#])(\||[^|](?2)[^|])(?!\1)[^|]/#$2#/&&redo' <<< ".##..#...|#..##...|..##....#."

ส่วนแรก ( ([.#])) และสุดท้าย ( (?!\1)[^|]) เหมือนกันกับในคำตอบของ Retina (ดูคำอธิบายที่นั่น)
ส่วนตรงกลาง ( (\||[^|](?2)[^|])) ใช้การเรียกซ้ำ perl ( (?2)) เพื่อจับคู่มิรเรอร์ ( \|) หรือ ( |) ตัวละครที่ไม่ใช่มิเรอร์( ) สองตัว[^|]คั่นด้วยรูปแบบเดียวกัน ( (?2))


รุ่นเก่า (และอัปลักษณ์) ของฉัน: s/([.#])(([^|]*)\|(??{$3=~s%.%[^|]%gr}))(?!\1)[^|]/#$2#/&&redo


4

Haskell (ไม่มี regex), 117 ไบต์

r=reverse
s=span(<'|')
m=zipWith min
g a|(b,l:c)<-s a,(d,e)<-s c=b++l:g(m(r b++[l,l..])d++e)|0<1=a
f x=m(g x)$r.g.r$x

2

PHP, 123 117 100 ไบต์

for($t=$argv[1];$t!=$s;)$t=preg_replace("%([.#])(\||[.#](?2)[.#])(?!\g1)[.#]%","#$2#",$s=$t);echo$t;

โปรแกรมรับอาร์กิวเมนต์บรรทัดคำสั่ง regex นำมาจาก @Martin Ender / Dada -rทำงานด้วย


@Zgarb คงที่ขอบคุณ
Titus

2

C, 176 ไบต์

void t(char*a){int x=0;for(int i=0;a[i];i++)if(a[i]=='|'){for(int j=x;a[j]&&j<=i*2-x;j++){if((a[j]==35)&&(a[2*i-j]==46)){a[2*i-j]=35;i=-1;}if((i-j)&&(a[j]=='|'))break;}x=i+1;}}

Ungolfed

void t(char*a)
{
    int x=0;
    for(int i=0;a[i];i++)
        if(a[i]=='|')
        {
            for(int j=x;a[j]&&j<=i*2-x;j++)
            {
                if((a[j]=='#')&&(a[2*i-j]=='.'))
                {
                    a[2*i-j]='#';
                    i=-1;
                    break;
                }
                if((i!=j)&&(a[j]=='|'))
                    break;
            }
            x=i+1;
        }
}

1
ฉันคิดว่าคุณสามารถบันทึกสองสามไบต์โดยการแทนที่'#'และ'.'ด้วย35และ46ตามลำดับ
artificialnull

รหัสนี้สามารถเล่นกอล์ฟได้ .. มาก
Mukul Kumar

ขอบคุณ artificialNull ที่บันทึกไว้ 3 ไบต์ '|' คือ 124 ดังนั้นจึงไม่ได้บันทึกอะไรเลย (แต่บางทีฉันควรจะเปลี่ยนมันดังนั้นมันจะสอดคล้องกัน แต่ยังไม่แน่ใจ) และ @Mukul, ฉันไม่เห็นจริงๆ, โดยไม่ต้องเปลี่ยนลอจิกไหลของมันอย่างมาก.
Eyal Lev

ตรวจสอบว่ารหัสนี้ทำงานได้ดีx,i,j;void t(char*a){while(a[i]++)if(a[i]=='|'){for(j=x;a[j++]&&j<=i*2-x;j++){if((a[j]==35)&&(a[2*i-j]==46)){a[2*i-j]=35;i=-1;break;}if((i-j)&&(a[j]=='|'))break;}x=i+1;}}- 170 ไบต์
Mukul Kumar

1
1 ไบต์เพิ่มเติมแทนที่ (i! = j) ด้วย (ij) และหากคุณกำลังจะติดกับ c ++ ดังนั้น atleast จะกำหนด int ทั้งหมดไว้ในที่เดียว ...
Mukul Kumar

1

JavaScript (ES6), 170 ไบต์

s=>s.replace(/#/g,(c,i)=>(g(i,-1),g(i,1)),g=(i,d,j=h(i,d))=>j-h(j=j+j-i,-d)|s[j]!='.'||(s=s.slice(0,j)+'#'+s.slice(j+1),g(j,d)),h=(i,d)=>s[i+=d]=='|'?i:s[i]?h(i,d):-1)&&s

Ungolfed:

function mirror(s) {
    for (var i = 0; i < s.length; i++) {
        // Reflect each # in both directions
        if (s[i] == '#') s = reflect(reflect(s, i, true), i, false);
    }
    return s;
}
function reflect(s, i, d) {
    // Find a mirror
    var j = d ? s.indexOf('|', i) : s.lastIndexOf('|', i);
    if (j < 0) return s;
    // Check that the destination is empty
    var k = j + (j - i);
    if (s[k] != '.') return s;
    // Check for an intervening mirror
    var l = d ? s.lastIndexOf('|', k) : s.indexOf('|', k);
    if (l != j) return s;
    // Magically duplicate the #
    s = s.slice(0, k) + '#' + s.slice(k + 1);
    // Recursively apply to the new #
    return reflect(s, k, d);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.