เขียนฟังก์ชั่นที่ส่งคืนออบเจกต์ที่ทำซ้ำได้ของจุดที่ถูกต้องทั้งหมด 4 ทิศทางติดกับ (x, y)


17

ความต้องการทั่วไปในคลาสอัลกอริทึมและวิทยาการคอมพิวเตอร์โดยทั่วไปคือการทำซ้ำ 4 ทิศทางในตารางหรือเมทริกซ์ (เช่นใน BFS หรือ DFS) สิ่งนี้ดูเหมือนจะส่งผลให้เกิดรหัส clunky และ verbose จำนวนมากที่มีการคำนวณและการเปรียบเทียบจำนวนมากภายในลูป ฉันเห็นวิธีการต่าง ๆ มากมาย แต่ฉันไม่สามารถสั่นคลอนความรู้สึกว่ามีวิธีรัดกุมกว่านี้

ความท้าทายคือการเขียนฟังก์ชั่นบริสุทธิ์ที่กำหนดความกว้างและความสูงของระนาบ จำกัดn, mที่จุดกำเนิด(0,0)และพิกัด(x,y)ที่สามารถเป็นตัวแทนของจุดที่ถูกต้องภายในระนาบนั้นส่งคืนวัตถุที่ซ้ำได้ของทุกจุดภายในระนาบที่มีทิศทาง 4 (x,y)เพื่อที่อยู่ติดกัน

เป้าหมายคือการกำหนดฟังก์ชั่นนี้ให้น้อยที่สุดเท่าที่จะเป็นไปได้

ตัวอย่างบางส่วนเพื่อช่วยแสดงให้เห็นถึงอินพุต / เอาต์พุตที่ถูกต้อง:

n = 5 (y-axis), m = 3 (x-axis) (zero-based)

matrix = [
    [A, B, C],
    [D, E, F],
    [G, H, I],
    [J, K, L],
    [M, N, O],
]

(x, y) => [valid iterable points]

E: (1, 1) => [(1, 0), (2, 1), (1, 2), (0, 1)]
A: (0, 0) => [(1, 0), (0, 1)]
L: (2, 3) => [(2, 2), (2, 4), (1, 3)]
N: (1, 4) => [(1, 3), (2, 4), (0, 4)]
n = 1 (y-axis), m = 1 (x-axis) (zero-based)

matrix = [
    [A],
]

(x, y) => [valid iterable points]

A: (0, 0) => []
n = 2 (y-axis), m = 1 (x-axis) (zero-based)

matrix = [
    [A],
    [B],
]

(x, y) => [valid iterable points]

A: (0, 0) => [(0, 1)]
B: (0, 1) => [(0, 0)]

และนี่คือตัวอย่าง (อันนี้ใน Python) ของฟังก์ชันที่ตรงตามเงื่อนไข:

def four_directions(x, y, n, m):
    valid_coordinates = []
    for xd, yd in [(1, 0), (0, 1), (-1, 0), (0, -1)]:
        nx, ny = x + xd, y + yd
        if 0 <= nx < m and 0 <= ny < n:
            valid_coordinates.append((nx, ny))
    return valid_coordinates

ตัวอย่างข้างต้นกำหนดฟังก์ชั่นที่มีชื่อ แต่ฟังก์ชั่นที่ไม่ระบุชื่อก็เป็นที่ยอมรับ

อินพุตn, m, x, yเป็นจำนวนเต็ม 32 บิตที่ไม่ได้ลงชื่อทั้งหมดภายในช่วงต่อไปนี้:

n > 0
m > 0
0 <= x < m
0 <= y < n

เอาต์พุตจะต้องอยู่ในรูปแบบของ iterable (อย่างไรก็ตามภาษาที่คุณเลือกกำหนดว่า) ของคู่ (x, y)

ชี้แจงเพิ่มเติม:

จำนวนเชิงซ้อน (และการแทน / การทำให้เป็นอนุกรมอื่น ๆ ) นั้นใช้ได้ตราบใดที่ผู้บริโภคของ iterable สามารถเข้าถึงได้xและyเป็นจำนวนเต็มที่รู้แค่ตำแหน่งที่ตั้ง

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


6
ยินดีต้อนรับสู่เว็บไซต์! ความท้าทายนี้ค่อนข้างดีตามมาตรฐานของเรา แต่มีสองสิ่งที่ตรงกับสไตล์ของเรา สำหรับคนที่เราชอบความท้าทายที่ไม่ จำกัด ภาษาเดียวถ้าเป็นไปได้ มันสนุกมากขึ้นเมื่อทุกคนสามารถแข่งขันได้ โดยทั่วไปเรายังให้คะแนนโค้ดกอล์ฟเป็นไบต์ซึ่งแตกต่างจากตัวละครพวกเขาเหมือนกันสำหรับจุดประสงค์ส่วนใหญ่ แต่มีสิ่งที่โกงสองสามอย่างที่คุณสามารถทำได้หากคำตอบนั้นทำด้วยตัวอักษร หวังว่าคุณจะสนุกที่นี่!
โพสต์ Rock Garf Hunter

เรารับประกันได้ว่า(x,y)ตัวเองอยู่ในรูปสี่เหลี่ยมผืนผ้าใช่มั้ย
xnor

4
โดยค่าเริ่มต้น CGCC ช่วยให้โปรแกรมเต็มรูปแบบเช่นเดียวกับฟังก์ชั่นการส่ง สิ่งนี้จะช่วยให้ภาษาที่ไม่จำเป็นต้องมีแนวคิดของฟังก์ชั่นในการแข่งขันเช่นกัน
Jo King

3
การส่งออกจะเป็น STDOUT มากกว่าวัตถุรหัส โดยทั่วไปสามารถเป็นเอาต์พุตใด ๆ ที่มีตัวคั่นชัดเจนดังนั้นจึงไม่มีความกำกวมและเป็นไปตามรูปแบบเอาต์พุตมาตรฐาน
King King

2
มันอนุญาตให้แสดงพิกัดเป็นตัวเลขที่ซับซ้อนมากกว่า tuples จำนวนเต็มหรือไม่
Joel

คำตอบ:


12

Python 2 , 66 ไบต์

lambda m,n,x,y:[(x-1,y),(x+1,y)][~x:m-x]+[(x,y-1),(x,y+1)][~y:n-y]

ลองออนไลน์!

แสดงรายชื่อเพื่อนบ้านทั้งสี่จากนั้นใช้การแบ่งส่วนรายการเพื่อลบรายการที่อยู่นอกขอบเขต


Python 2 , 71 ไบต์

lambda m,n,x,y:[(k/n,k%n)for k in range(m*n)if(k/n-x)**2+(k%n-y)**2==1]

ลองออนไลน์!

แทนการตรวจสอบซึ่งในสี่ของเพื่อนบ้านอยู่ในขอบเขตที่เราทำมันเป็นวิธีที่ช้าลงของการตรวจสอบทุกจุดในขอบเขตสำหรับผู้ที่เป็นเพื่อนบ้านที่เป็นมีระยะทาง Euclidian (x,y)ตรงจาก นอกจากนี้เรายังใช้เคล็ดลับ div-modแบบคลาสสิกเพื่อย้ำผ่านกริดทำให้ไม่จำเป็นต้องเขียนสองลูปเหมือนfor i in range(m)for j in range(n)กัน

ฉันพยายามใช้เลขคณิตที่ซับซ้อนเพื่อเขียนสภาพระยะทาง แต่มันกลับกลายเป็นว่าจะเขียนนานabs((k/n-x)*1j+k%n-y)==1ขึ้น


Python 2 , 70 ไบต์

lambda m,n,x,y:[(x+t/3,y+t%3-1)for t in-2,0,2,4if m>x+t/3>=0<y+t%3<=n]

ลองออนไลน์!


11
ขอแสดงความยินดีกับ 100k!
Arnauld

4

อ็อกเทฟ 90 ไบต์

วิธีนี้ใช้วิธีทางเรขาคณิต: ก่อนอื่นเราจะสร้างเมทริกซ์ของศูนย์ที่มีขนาดที่ต้องการและตั้งค่าเป็น1ตำแหน่งที่ต้องการ จากนั้นเราก็ติดต่อกับเคอร์เนล

[0, 1, 0]
[1, 0, 1]
[0, 1, 0]

ซึ่งสร้างเมทริกซ์ใหม่ที่มีขนาดเท่ากันกับที่อยู่ที่ 4 เพื่อนบ้านของจุดเดิม จากนั้นเราfind()เป็นดัชนีของรายการที่ไม่ใช่ศูนย์ของเมทริกซ์ใหม่นี้

function [i,j]=f(s,a,b);z=zeros(s);z(a,b)=1;[i,j]=find(conv2(z,(v=[1;-1;1])*v'<0,'same'));

ลองออนไลน์!

convolution เป็นกุญแจสู่ความสำเร็จ


4
ไม่ว่าแบบอักษรจะเล็กเพียงใด
Luis Mendo

3

ภาษา Wolfram (Mathematica) , 42 ไบต์

Cases[List~Array~#2,a_/;Norm[a-#]==1,{2}]&

ลองออนไลน์!

1-indexed (ซึ่งเป็นไปตามอนุสัญญา Mathematica สำหรับการจัดทำดัชนี) {x,y}, {m,n}จะเข้าเป็น


สำหรับ I / O ที่จัดทำดัชนี 0, 45 ไบต์ :

Cases[Array[List,#2,0],a_/;Norm[a-#]==1,{2}]&

ลองออนไลน์!


3

JavaScript (ES6), 74 ไบต์

วิธีการที่น่าเบื่อ

(h,w,x,y)=>[x&&[x-1,y],~x+w&&[x+1,y],y&&[x,y-1],++y-h&&[x,y]].filter(_=>_)

ลองออนไลน์!


JavaScript (Node.js) , 74 ไบต์

น่าเบื่อน้อยลง แต่ใช้เวลานาน ([h,w,x,y])จะเข้าเป็น

a=>a.flatMap((_,d,[h,w,x,y])=>~(x+=--d%2)*~(y+=--d%2)&&x<w&y<h?[[x,y]]:[])

ลองออนไลน์!


JavaScript (V8) , 67 ไบต์

หากอนุญาตวิธีการส่งออกมาตรฐานทั้งหมดเราสามารถพิมพ์พิกัดที่ถูกต้องด้วย:

(h,w,x,y)=>{for(;h--;)for(X=w;X--;)(x-X)**2+(y-h)**2^1||print(X,h)}

ลองออนไลน์!


2

เยลลี่ ,  13  12 ไบต์

2ḶṚƬNƬẎ+⁸%ƑƇ

การเชื่อมโยง dyadic ยอมรับของทั้งสองรายการ (0-จัดทำดัชนี) จำนวนเต็มด้านซ้าย, [row, column]และสองจำนวนเต็มด้านขวาซึ่งอัตราผลตอบแทนรายชื่อของรายการของจำนวนเต็มให้[height, width][[adjacent_row_1, adjacent_column_1], ...]

ลองออนไลน์!

อย่างไร?

2ḶṚƬNƬẎ+⁸%ƑƇ - Link: [row, column]; [height, width]   e.g. [3,2]; [5,3] (the "L" example)
2            - literal 2                                   2
 Ḷ           - lowered range                               [0,1]
   Ƭ         - collect up while distinct, applying:
  Ṛ          -   reverse                                   [[0,1],[1,0]]
     Ƭ       - collect up while distinct, applying:
    N        -   negate                                    [[[0,1],[1,0]],[[0,-1],[-1,0]]]
      Ẏ      - tighten                                     [[0,1],[1,0],[0,-1],[-1,0]]
        ⁸    - chain's left argument ([row, column])       [3,2]
       +     - add (vectorises)                            [[3,3],[4,2],[3,1],[2,2]]
           Ƈ - filter keep if:
          Ƒ  -   is invariant under:
         %   -     modulo ([height, width]) (vectorises)    [3,0] [4,2] [3,1] [2,2]
             - (...and [3,0] is not equal to [3,3] so ->)  [[4,2],[3,1],[2,2]]

คุณสามารถแทนที่ด้วยḶṚƬ return ขณะที่return และเนื่องจากมีการห่อ singletons จะมีเฉพาะ vectorizes ที่มีองค์ประกอบแรกของสำหรับเหล่านั้นดังนั้นพวกเขาจึงทำหน้าที่เหมือนองค์ประกอบที่สองของพวกเขาคือ(ตัวตนเพิ่มเติม) ดังนั้นคำสั่งของเอาต์พุตอาจเปลี่ยนแปลงได้ Ṭ€2ḶṚƬNƬẎ[[0, 1], [1, 0], [0, -1], [-1, 0]]2Ṭ€NƬẎ[[1], [0, 1], [-1], [0, -1]]+0
Erik the Outgolfer

2

Perl 6 , 56 49 ไบต์

-7 ไบต์ขอบคุณ nwellnhof!

{grep 1>(*.reals Z/@^b).all>=0,($^a X+1,-1,i,-i)}

ลองออนไลน์!

ลบออกจากองค์ประกอบขอบเขตโดยตรวจสอบว่าเมื่อแบ่งตามขอบเขตอาร์เรย์อยู่ระหว่าง 0 และ 1 นำเข้าและส่งออกผ่านทางตัวเลขที่ซับซ้อนที่มีส่วนร่วมที่แท้จริงคือการประสานงานและจินตนาการเป็นx yคุณสามารถแยกสิ่งเหล่านี้ผ่านทาง.imและ.reฟังก์ชั่น



@nwellnhof ดีมาก! ฉันจะสร้างมันขึ้นมาเพื่อทำสิ่งนี้แต่divดูเหมือนจะไม่ทำงานเพื่อNums
Jo King

(*.reals>>.Int Zdiv@^b).noneหรือใช้(*.reals Z/@^b)>>.Int.noneงานได้ แต่ Int-cast ดูเหมือนจะมีราคาแพงเกินไป
nwellnhof

1

J , 30 29 28 ไบต์

(([+.@#~&,1=|@-)j./)~j./&i./

ลองออนไลน์!

วิธี:

  • เลี้ยวmx ทางขวามือnให้เป็นตารางของจำนวนเชิงซ้อนj./&i./
  • หาเรื่องหาเรื่องซ้าย (จุดของเรา) j./
  • สร้างรูปแบบการแสดงที่ระยะห่างระหว่างจุดของเราและกริดคือ 1 1=|@-
  • ใช้เพื่อกรองกริดหลังจากทำให้ทั้งสองแบน #~&,
  • เปลี่ยนผลลัพธ์กลับเป็นคะแนนจริง +.@


0

ถ่าน 29 ไบต์

Jθη#FIζFIε«Jικ¿№KV#⊞υ⟦ικ⟧»⎚Iυ

ลองออนไลน์! การเชื่อมโยงคือการใช้รหัสเวอร์ชันอย่างละเอียด รับอินพุตตามลำดับ x, y, width, height คำอธิบาย:

Jθη#

พิมพ์ #ที่ตำแหน่งที่จัดไว้

FIζFIε«

วนซ้ำสี่เหลี่ยมที่กำหนด

Jικ

ข้ามไปยังตำแหน่งปัจจุบัน

¿№KV#⊞υ⟦ικ⟧

หากมีการติดกัน #ให้บันทึกตำแหน่ง

»⎚Iυ

เอาต์พุตตำแหน่งที่ค้นพบในตอนท้ายของลูป

คำตอบที่น่าเบื่อ:

FIζFIε¿⁼¹⁺↔⁻ιIθ↔⁻κIηI⟦ικ

ลองออนไลน์! การเชื่อมโยงคือการใช้รหัสเวอร์ชันอย่างละเอียด ทำงานโดยการค้นหาตำแหน่งที่อยู่ติดกันทางคณิตศาสตร์


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