Sihirli ayna delilik


22

Giriş

Sihirli aynalarla dolu bir odam var . Onlar başka bir sihirli ayna dışında herhangi bir öğeyi kopyalayabilen gizemli eserlerdir. Daha açık bir şekilde, öğenin yinelenen bir sürümü aynanın diğer tarafında, aynı mesafede görünecektir. Bununla birlikte, her iki tarafta da, çoğaltma aynası ve her iki öğe arasında (orijinal veya kopya) başka bir sihirli ayna varsa, kopya oluşturulmaz. Orijinal öğe aynanın solunda veya sağında olabilir ve kopya diğer tarafta görünecektir. Ayrıca, yinelenen öğenin kendisi başka bir yansıtmayla çoğaltılabilir. Öğeler başka öğelerin çoğaltılmasını hiçbir zaman engellemez (doğrudan çoğaltılacak konumda olma durumu hariç).

Giriş

Girişiniz, .#|boş alanı, öğeleri ve sihirli aynaları temsil eden karakterlerden oluşan bir dizedir . Girdide her zaman en az bir sihirli ayna olacak.

Çıktı

Çıktınız, yukarıda belirtilen kurallara göre her sihirli aynanın yapabildiği her öğeyi kopyaladığı başka bir dize olacaktır. Yinelenen bir öğenin göründüğü yerde her zaman boş bir alan olacağını varsayabilirsiniz (böylece sınırların dışına çıkmazlar).

Örnekler

Giriş dizesini göz önünde bulundurun

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

netlik için bazı pozisyonları işaretledik. Ayna , sağa biten Böğeyi çoğaltır A:

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

Ayna Cdaha sonra yeni öğeyi çoğaltır:

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

Ayna Cöğeyi yinelenen olamaz Aayna beri, Bbir şekilde olduğunu. DAynanın Böbür tarafında olduğu için, öğeyi kopyalayamaz . Aynı şekilde, yansıtma işlemi gerçekleştirildiği Biçin yansıtma işlemi öğenin Dveya yanındaki kopyalamayı çoğaltamaz, bu Cnedenle doğru çıktı budur.

Başka bir örnek için girişi düşünün

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

Ayna Dçoğaltabilirsiniz Ave Bsağa ve Eve Gsola. Cve Fzaten birbirlerinin kopyası. Dize olur

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

Ayna Hçoğaltabilirsiniz E, Fve tekrarı Ave Bsağında ve Isolunda. Gve Jzaten birbirinin kopyası, ayna Dise öyle K. Şimdi biz var

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

Son olarak, ayna sola Dkopyalarını çoğaltabilir I. Biz sona

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

Kurallar ve puanlama

Tam bir program veya bir fonksiyon yazabilirsiniz. En düşük bayt sayısı kazanır. Regex motorlarını kullanmayan gönderimler, yapılanlardan ayrı olarak rekabet eder ve ile işaretlenebilir (regex yok) .

Test durumları

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

Girdi ve / veya çıktı olarak bir dizi karakter alabilir miyiz?
Conor O'Brien,

@ ConorO'Brien Hayır, sizin dilinizde bir dizgenin doğal temsili olmadıkça.
Zgarb

Yanıtlar:


10

Retina , 50 bayt

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

Çevrimiçi deneyin! (İlk satır satır besleme ile ayrılmış bir test takımı sağlar.)

Sanırım bu (regex yok) yapılan bir sunumun tam tersi.

açıklama

Bu sadece +dize değişimini durdurana kadar tekrar tekrar ( ) uygulanan bir regex ikamesidir . Aynalı iki konumun verilen aynayla aynı mesafede olduğundan emin olmak için dengeleme grupları kullanıyorum (geri referanslar yapmaz, çünkü her iki taraftaki tam dize |farklı olabilir).

([#.])            # 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.

Bu, #$2#eşleşmenin hem ilk hem de son karakterini a ile değiştiren yerine geçer #.


9

Perl, 49 bayt

Bu regex benimkinden daha kısa 15 bayt önerdi bunun için @Martin Ender için tam kredi .

47 bayt kod + -plbayrakları

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

Çalıştırmak için:

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

İlk ( ([.#])) ve son ( (?!\1)[^|]) kısımlar Retina cevabındakiyle aynıdır (oradaki açıklamaya bakınız).
Orta kısım ( (\||[^|](?2)[^|])), aynı desenle ( ) ayrılmış (?2)bir ayna ( \|) veya ( |) iki ayna olmayan karakter ( [^|]) ile eşleşmek için perl recursion ( ) işlevini kullanır (?2).


Eski (ve çirkin) sürümüm: s/([.#])(([^|]*)\|(??{$3=~s%.%[^|]%gr}))(?!\1)[^|]/#$2#/&&redo


4

Haskell (düzenli ifade yok), 117 bayt

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 bayt

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

program @Martin Ender / Dada'dan alınan komut satırı argümanını alıyor. İle koş -r.


@Zgarb düzeltildi, teşekkürler
Titus

2

C, 176 bayt

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
Sana değiştirerek bir çift bayt kurtarabilir miyiz '#'ve '.'ile 35ve 46sırasıyla.
yapay

Bu kod çok fazla olabilir.
Mukul Kumar

Teşekkürler artificialNull, 3 bye kazandı. '|' 124, yani hiçbir şey kaydetmiyor (ama belki de onu değiştirmeliyim, bu yüzden tutarlı olacak; henüz emin değilim). ve @Mukul, mantık akışını büyük ölçüde değiştirmeden nasıl yapılacağını gerçekten göremiyorum.
Eyal Lev

Bu kodun düzgün çalışıp 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;}}
çalışmadığını

1
1 bayt, (i! = J) 'i (ij) ile değiştirir ve c ++' a sadık kalırsanız, sonra atleast tüm
int'yi

1

JavaScript (ES6), 170 bayt

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);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.