Izgara geçiş sırası


17

Bir grafik kağıdı alıp mbirimleri sağa ve nbirimleri yukarı doğru eğimli bir çizgi çizerseniz ,n-1 yatay ve m-1dikey kılavuz çizgilerini bir sıra halinde kesersiniz. Bu dizinin çıktısını almak için kod yazın.

Örneğin, m=5ve n=3verir:

Gridlines crossing for m=5, n=3

Muhtemel ilgili: Öklid ritimlerinin oluşturulması , üretme Fibonacci tilings , FizzBuzz

Girdi:m,n Nispeten asal olan iki pozitif tamsayı

Çıktı: Geçişleri iki ayrı token dizisi olarak döndürün veya yazdırın. Örneğin, bir dize olabilir Hve V, bir listesi TrueveFalse ya 0sitesindeki ve 1'ayrı çizgiler üzerine basılmış s. Değişken sayıda boşluk olmadığı gibi her zaman aynı olduğu sürece jetonlar arasında bir ayırıcı olabilir.

Test senaryoları:

İlk test durumu boş çıktı verir veya hiç çıktı vermez.

1 1 
1 2 H
2 1 V
1 3 HH
3 2 VHV
3 5 HVHHVH
5 3 VHVVHV
10 3 VVVHVVVHVVV
4 11 HHVHHHVHHHVHH
19 17 VHVHVHVHVHVHVHVHVVHVHVHVHVHVHVHVHV
39 100 HHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHH

Biçiminde (m,n,output_as_list_of_0s_and_1s):

(1, 1, [])
(1, 2, [0])
(2, 1, [1])
(1, 3, [0, 0])
(3, 2, [1, 0, 1])
(3, 5, [0, 1, 0, 0, 1, 0])
(5, 3, [1, 0, 1, 1, 0, 1])
(10, 3, [1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1])
(4, 11, [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0])
(19, 17, [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1])
(39, 100, [0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0])

2
Bugün PPCG'de: golf Bresenham'ın Çizgi Çizme Algoritması
Sparr

Eklediğiniz alternatif formata dayanarak, giriş, çıktının bir parçası olarak tekrarlanabilir mi / gerekli mi? Aksi takdirde, giriş ve çıkışın neden aynı listenin bir parçası olduğunu anlamıyorum.
Reto Koradi

@RetoKoradi Hayır, girdiyi eklememelisiniz. Test senaryolarını işlemeyi kolaylaştırmak için tuples'e koydum.
xnor

Cevabı tahmin edebilirim, ama sormak acı veremez: Boşluk karakterini çıktı belirteçlerinden biri olarak kullanmak kabul edilebilir mi? Bunun bir sonucu, çıktıda önemli öncü / arka boşluklar olabileceğidir. Başka alan olmayacaktı, bu yüzden tüm alanlar önemli olacaktı.
Reto Koradi

@RetoKoradi Hayır, çünkü arkadaki boşluklar görünmüyor.
xnor

Yanıtlar:


7

Ruby, 92; Devekuşu 0.7.0 , 38

f=->m,n{((1..m-1).map{|x|[x,1]}+(1..n-1).map{|x|[1.0*x*m/n,0]}).sort_by(&:first).map &:last}
:n;:m1-,{)o2W}%n1-,{)m n/*0pW}%+_H$_T%

Her ikisi için de çıktı 1'ler ve 0'lar kullanır (ör. 101101).


İşte Devekuşu'nun bir açıklaması:

:n;:m    store n and m as variables, keep m on the stack
1-,      from ex. 5, generate [0 1 2 3]
{...}%   map...
  )        increment, now 5 -> [1 2 3 4]
  o        push 1 (the digit 1 is special-cased as `o')
  2W       wrap the top two stack elements into an array
           we now have [[1 1] [2 1] [3 1] [4 1]]
n1-,     doing the same thing with n
{...}%   map...
  )        increment, now 3 -> [1 2]
  m n/*    multiply by slope to get the x-value for a certain y-value
  0        push 0
  pW       wrap the top two stack elements (2 is special-cased as `p')
+        concatenate the two arrays
_H$      sort-by first element (head)
_T%      map to last element (tail)

Ruby kodunu kılavuz olarak kullanarak, her şeyin nasıl çalıştığına dair bir açıklama:

f = ->m,n {
    # general outline:
    # 1. collect a list of the x-coordinates of all the crossings
    # 2. sort this list by x-coordinate
    # 3. transform each coordinate into a 1 or 0 (V or H)
    # observation: there are (m-1) vertical crossings, and (n-1) horizontal
    #   crossings. the vertical ones lie on integer x-values, and the
    #   horizontal on integer y-values
    # collect array (1)
    (
        # horizontal
        (1..m-1).map{|x| [x, 1] } +
        # vertical
        (1..n-1).map{|x| [1.0 * x * m/n, 0] }  # multiply by slope to turn
                                               # y-value into x-value
    )
    .sort_by(&:first)  # sort by x-coordinate (2)
    .map &:last        # transform into 1's and 0's (3)
}

5

Python, 53

Bu, Doğru / Yanlış liste çıktısını kullanır. Burada özel bir şey yok.

lambda m,n:[x%m<1for x in range(1,m*n)if x%m*(x%n)<1]

4

Pyth - 32 24 bayt

Jmm,chk@Qddt@Qd2eMS+hJeJ

Format ile stdin üzerinden girdi alır [m,n]. Sonucu, 0 = V ve 1 = H olan stdout'a 0 ve 1'lerin listesi olarak yazdırır.

Çevrimiçi test edin


Açıklama:

J                           # J = 
 m             2            # map(lambda d: ..., range(2))
  m        t@Qd             # map(lambda k: ..., range(input[d] - 1))
   ,chk@Qdd                 # [(k + 1) / input[d], d]
                eMS+hJeJ    # print map(lambda x: x[-1], sorted(J[0] + J[-1])))

Eşleme zamanınız için sözdizimsel harita operatörünü kullanarak bir bayt kaydedebilirsiniz. eMile aynıdır med.
Maltysen

Ayrıca, sadece dışarı alabilir @"VH"yazdırmak için izin verilir beri 0ve 1yerine Vve H.
Maltysen

İle satır içi atamayı kullanarak başka bir bayt kaydedebilirsiniz J. Şimdiye kadar 25 baytta
Maltysen

@Maltysen, teşekkürler jkçıktı bir liste olabilir gibi kaldırabilirsiniz düşünüyorum .
Tyilo

Satır içi atama hakkındaki yorumuma 23 göz atabilirsiniz.
Maltysen

4

IA-32 makine kodu, 26 bayt

Onaltılık kod:

60 8b 7c 24 24 8d 34 11 33 c0 2b d1 74 08 73 03
03 d6 40 aa eb f2 61 c2 04 00

Aşağıdaki C kodundan başladım:

void doit(int m, int n, uint8_t* out)
{
    int t = m;
    while (true)
    {
        if (t >= n)
        {
            t -= n;
            *out++ = 1;
        }
        else
        {
            t += m;
            *out++ = 0;
        }
        if (t == n)
            break;
    }
}

Çıkışı sağlanan ara belleğe yazar. Çıktının uzunluğunu döndürmez, ancak gerçekten gerekli değildir: çıkış uzunluğu her zaman m + n - 2:

int main()
{
    char out[100];
    int m = 10;
    int n = 3;
    doit(m, n, out);
    for (int i = 0; i < m + n - 2; ++i)
    {
        printf("%d ", out[i]);
    }
}

C kodunu makine koduna dönüştürmek için, önce if/elsedallardan birini boş bırakmak ve 0bunun yerine karşılaştırmak için biraz değişiklik yaptım n:

void doit(int m, int n, char* out)
{
    int t = n;
    while (true)
    {
        int r = 0;
        t -= m;
        if (t == 0)
            break;
        if (t >= 0)
        {
        }
        else
        {
            t += m + n;
            ++r;
        }
        *out++ = r;
    }
}

Buradan, satır içi montaj kodunu yazmak basittir:

__declspec(naked) void __fastcall doit(int x, int y, char* out)
{
    _asm
    {
        pushad;                 // save all registers
        mov edi, [esp + 0x24];  // edi is the output address
        lea esi, [ecx + edx];   // esi is the sum m+n
    myloop:                     // edx is the working value (t)
        xor eax, eax;           // eax is the value to write (r)
        sub edx, ecx;
        jz myout;
        jae mywrite;
        add edx, esi;
        inc eax;
    mywrite:
        stosb;                  // write one value to the output
        jmp myloop;
    myout:
        popad;                  // restore all registers
        ret 4;                  // return (discarding 1 parameter on stack)
    }
}

Merak ediyorum - bu algoritma neden çalışıyor?
xnor

@xnor Gayri resmi olarak fizzbuzz dizisini izler . İşte t"uzaklık buzz". Eğer mesafe en azından n, git fizz, başka git buzz; mesafeyi güncelleyin; 0'a kadar tekrarlayın.
anatolyg

3

Python - 125 bayt

Çok basit bir algoritma kullanır, sadece koordinatları arttırır ve çizgileri geçtiğinde ve çıktısı aldığında algılar. Pyth'e çevirmek istiyorum.

a,b=input()
i=1e-4
x=y=l=o=p=0
k=""
while len(k)<a+b-2:x+=i*a;y+=i*b;k+="V"*int(x//1-o//1)+"H"*int(y//1-p//1);o,p=x,y
print k

Döngü sayısını kontrol ederken l ines ve sonra değerlerden herhangi birinin çıkartılarak bir sınırın ötesine geçip geçmediğini kontrol eder.

Stdin'den girdi 39, 100alır ve HHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHbir satırda stdout gibi yazdırır .


3

CJam, 15 bayt

Ll~_:*,\ff{%!^}

Burada deneyin.

Yazdırır 01 V ve10 H için .

açıklama

L          e# An empty list.
l~         e# Evaluate the input.
_:*,       e# [0, m*n).
\          e# The input (m and n).
ff{%!      e# Test if each number in [0, m*n) is divisible by m and n.
^}         e# If divisible by m, add an 10, or if divisible by n, add an 01 into
           e# the previous list. If divisible by neither, the two 0s cancel out.
           e# It's just for output. So we don't care about what the previous list
           e# is -- as long as it contains neither 0 or 1.

Çapraz çizgi, tüm çapraz çizginin her 1 / n'si için yatay bir çizgiyi geçer ve her 1 / m için dikey bir çizgiyi keser.


Bunun için bir açıklama ekler misiniz? Çok ilgi çekici, ama en azından ilk bakışta neden çalıştığını anlamıyorum. Onunla oynayarak, sadece göreli asal değerler (problem tanımında verilen) için çalıştığını fark ederken, benimki tüm değerler için çalışıyor. Dolayısıyla temeldeki matematik çok farklıdır.
Reto Koradi

Biraz daha batmasına izin verdikten sonra, en azından algoritma kısmını anladığımı düşünüyorum. Çıktı oluşturma mantığını daha sonra incelemek zorundayız.
Reto Koradi

@RetoKoradi Düzenlendi.
jimmy23013

2

TI-BASIC, 32

Prompt M,N
For(X,1,MN-1
gcd(X,MN
If log(Ans
Disp N=Ans
End

Basit. Çizgi satırlarına ayrılmış 0ve bir dizi 1satır kullanır. TI-BASIC'in avantajları iki bayt gcd(ve zımni çarpmadır, ancak dezavantajları son değeri içeren For döngüsü ve giriş için harcanan 5 bayttır.



1

Haskell, 78 bayt

import Data.List
m#n=map snd$sort$[(x,0)|x<-[1..m-1]]++[(y*m/n,1)|y<-[1..n-1]]

Kullanım örneği:

*Main> 19 # 17
[0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]
*Main> 10 # 3
[0,0,0,1,0,0,0,1,0,0,0]

Nasıl Çalışır: tüm dikey geçişleri x değerlerinin bir listesini yapmak (x,0)için x[1,2, ..., M-1] (de 0dikey gösterir) ve yatay geçitleri x değerlerinin listesini ekler (y*m/n,1)için yde [1,2, ..., n-1] ( 1yatay anlamına gelir). Çiftlerin ikinci elemanlarını sıralayın ve alın.

Günün Lanet: tekrar ben harcanan 17 bayt zorunda importçünkü sortiçindedir Data.Liststandart kütüphanede değil.


1

KDB (Q), 44 bayt

{"HV"0=mod[asc"f"$1_til[x],1_(x*til y)%y;1]}

açıklama

Kesişim noktalarının tüm x ekseni değerlerini bulun ve sıralayın. Mod 1 sıfır ise "V", sıfır olmayan "H" dir.

Ölçek

q){"HV"0=mod[asc"f"$1_til[x],1_(x*til y)%y;1]}[5;3]
"VHVVHV"

1

CJam, 26 24 bayt

l~:N;:M{TN+Mmd:T;0a*1}*>

Çevrimiçi deneyin

Çok basit, hemen hemen Bresenham tipi algoritmanın doğrudan uygulanması.

Açıklama:

l~    Get input and convert to 2 integers.
:N;   Store away N in variable, and pop from stack.
:M    Store away M in variable.
{     Loop M times.
  T     T is the pending remainder.
  N+    Add N to pending remainder.
  M     Push M.
  md    Calculate div and mod.
  :T;   Store away mod in T, and pop it from stack
  0a    Wrap 0 in array so that it is replicated by *, not multiplied.
  *     Emit div 0s...
  1     ... and a 1.
}*      End of loop over M.
>       Pop the last 1 and 0.

Sonuncusu 01atmak gerekiyor çünkü döngü, istenen çıkışın bir parçası olmayan bitiş noktasına kadar gitti. Biz ki Not değil basitçe, Aksi takdirde 1 ile döngü sayısını azaltmak N > Mhepsi 0sadece en son kurtulmak gerekir iken, son yineleme gelen ler eksik olacak 0.


1
Sen kullanabilirsiniz >için ;W<.
jimmy23013

@ jimmy23013 İyi fikir. 1Yığının üstünde bir tane olduğumu bildiğim için üretken olarak da kullanabilirim.
Reto Koradi
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.