Phù hợp với chủ đề đăng ký MQTT


10

Lý lịch

MQTT (Truyền tải hàng đợi từ xa tin nhắn) là một giao thức nhắn tin dựa trên đăng ký theo tiêu chuẩn ISO ( Wikipedia ).

Mỗi tin nhắn có một chủ đề, chẳng hạn như các ví dụ sau:

  • myhome/groundfloor/livingroom/temperature
  • USA/California/San Francisco/Silicon Valley
  • 5ff4a2ce-e485-40f4-826c-b1a5d81be9b6/status
  • Germany/Bavaria/car/2382340923453/latitude

Khách hàng MQTT có thể đăng ký chủ đề tin nhắn bằng cách sử dụng ký tự đại diện:

  • Cấp một: +
  • Tất cả các cấp trở đi: #

Ví dụ: đăng ký myhome/groundfloor/+/temperaturesẽ tạo ra các kết quả này (không phù hợp in đậm ):

✅ MyHome / trệt / phòng khách / nhiệt độ
✅ MyHome / trệt / bếp / nhiệt độ
❌ MyHome / trệt / phòng khách / sáng
❌ MyHome / firstfloor / phòng khách / nhiệt độ
gara / trệt / tủ lạnh / nhiệt độ

Trong khi đó, thuê bao +/groundfloor/#sẽ tạo ra những kết quả này:

✅ myhome / groundfloor / phòng khách / nhiệt độ
✅ myhome / groundfloor / bếp / độ sáng
✅ nhà để xe / tầng trệt / tủ lạnh / nhiệt độ / hơn / cụ thể / lĩnh vực
❌ myhome / Firstfloor / phòng khách / nhiệt độ
myhome / tầng hầm / góc

Thêm thông tin ở đây .

Nhiệm vụ

Thực hiện một chức năng / chương trình chấp nhận hai chuỗi và trả về một boolean. Chuỗi đầu tiên là chủ đề chủ đề, thứ hai là chủ đề tiêu chí. Chủ đề tiêu chí sử dụng cú pháp đăng ký chi tiết ở trên. Các chức năng là trung thực khi đối tượng phù hợp với tiêu chí.

Quy tắc cho nhiệm vụ này:

  • Chủ đề là ASCII
  • Không có trường tiêu chí nào ngoài #ký tự đại diện
  • Ký tự đại diện không xuất hiện trong chủ đề
  • Số trường chủ đề> = số trường tiêu chí
  • Không có trường 0 ký tự cũng không có dấu gạch đầu dòng hoặc đuôi phía trước

Các trường hợp thử nghiệm

iteria1 = "myhome / groundfloor / + / nhiệt độ" iteria2
= "+ / groundfloor / #"

("abc", "ab") => false
("abc", "abc") => true
("abc / de", "abc") => false
("myhome / groundfloor / phòng khách / nhiệt độ", tiêu chí1 ) => true
("myhome / groundfloor / Kitchen / nhiệt độ",
iteria1 ) => true ("myhome / groundfloor / Livingroom / độ sáng",
iteria1 ) => false ("myhome / Firstfloor / Livingroom / nhiệt độ", iteria1) > false
("gara / groundfloor / tủ lạnh / nhiệt độ",
iteria1 ) => false ("myhome / groundfloor / Livingroom / nhiệt độ",
iteria2 ) => true ("myhome / groundfloor / Kitchen / độ sáng", iteria2) => true
("nhà để xe / mặt đất / tủ lạnh / nhiệt độ / nhiều hơn / cụ thể / lĩnh vực ", tiêu
chí2 ) => đúng (" myhome / Firstfloor / phòng khách / nhiệt độ ", iteria2) => sai
("myhome / tầng hầm / góc / nhiệt độ", iteria2) => false
("âm nhạc / kei $ ha / mới nhất", "+ / kei $ ha / +") => true


@HyperNeutrino, đó là một câu hỏi hay. Tôi đang ở trên hàng rào. Chủ đề a/b/csẽ không phù hợp với tiêu chí a/b, vì vậy tôi có xu hướng nói Không .
Patrick

4
Là /, + và # được đảm bảo không bao giờ xuất hiện trong các phần chủ đề?
Jonathan Allan

Tôi thấy trong blog được liên kết rằng "Ngoài ra, dấu gạch chéo về phía trước là một chủ đề hợp lệ" nhưng không đề cập đến + và #, vì vậy tôi đoán hai cái này có thể.
Jonathan Allan

1
@Jonathan ALLan Từ docs.oocation-open.org/mqtt/mqtt/v3.1.1/os/iêu : Các ký tự đại diện có thể được sử dụng trong Bộ lọc chủ đề, nhưng KHÔNG được sử dụng trong Tên chủ đề
Nick Kennedy

2
@NickKennedy - đào đẹp, nhưng chúng tôi thực sự không cần.
Jonathan Allan

Câu trả lời:


3

Thạch , 20 byte

ṣ€”/ZṖF”#eƊ¿œiÐḟ”+ZE

Liên kết đơn âm chấp nhận danh sách các danh sách các ký tự, tương ứng [topic, pattern]trả về 1hoặc 0cho khớp hoặc không khớp.

Hãy thử trực tuyến! Hoặc xem một bộ thử nghiệm .

Làm sao?

ṣ€”/ZṖF”#eƊ¿œiÐḟ”+ZE - Link: list of lists of characters, [topic, pattern]
 €                   - for each:
ṣ                    -   split at occurrences of:
  ”/                 -     '/' character
    Z                - transpose (any excess of topic is kept)
           ¿         - while...
          Ɗ          - ...condition: last three links as a monad:
       ”#            -   '#' character
         e           -   exists in:
      F              -     flatten
     Ṗ               - ...do: pop the tail off
              Ðḟ     - filter discard those for which:
            œi       -   first multi-dimensional index of: ([] if not found, which is falsey)
                ”+   -     '+' character
                  Z  - transpose
                   E - all equal?

2

Ruby , 65 byte

Giải pháp Regex. Tôi đã thêm vào Regex.escapetrong trường hợp một tên tiêu chí chỉ là một cái gì đó giống như com.java/string[]/\nhoặc một cái gì đó ngớ ngẩn sẽ có các mảnh regex.

->s,c{s=~/^#{Regexp.escape(c).sub('\#','.*').gsub'\+','[^/]*'}$/}

Hãy thử trực tuyến!

Giải pháp phi regex, 77 byte

Sử dụng một kỹ thuật chia, zip và kết hợp đơn giản đẹp. Tôi đã phát triển cái này trước khi nhận ra rằng ngay cả với Regex.escapegiải pháp regex cũng sẽ ngắn hơn.

->s,c{s.split(?/).zip(c.split ?/).all?{|i,j|i==j||'+#'[j||9]||!j&&c[-1]==?#}}

Hãy thử trực tuyến!


.*?nên làm việc tại chỗ [^/]*.
Vụ kiện của Quỹ Monica

@NicHartley sẽ kích hoạt kết quả khớp sai cho các tiêu chí a/+/dvới chủ đềa/b/c/d
Ink Ink

Ah, nó sẽ như vậy. Việc gói nó trong một nhóm nguyên tử sẽ sửa nó, nhưng sau đó dài hơn hai byte. Ồ tốt
Vụ kiện của Quỹ Monica


1

Python 3 , 72 byte

lambda a,b:bool(re.match(b.translate({43:"[^/]+",35:".+"}),a))
import re

Hãy thử trực tuyến!

Vấn đề này có thể được đơn giản hóa một cách tầm thường thành một trận đấu regex, mặc dù một phương pháp khác thú vị hơn có thể mang lại kết quả tốt hơn.

EDIT Tôi đã đưa ra một giải pháp 107 byte không sử dụng regex. Tôi không biết liệu nó có thể ngắn hơn 72 hay có thể tôi không thấy cách tiếp cận chính xác cho vấn đề này. Chỉ là cấu trúc split-zip dường như quá lớn. Dùng thử trực tuyến!


2
Nếu chuỗi chứa bất kỳ ký tự regex nào khác, điều này có thể thất bại. Tôi sẽ xem xét điều đó mặc dù không có trường hợp thử nghiệm hiện tại nào có chứa bất cứ thứ gì giống như regex từ xa.
Mực giá trị

... giống như f('myhome/ground$floor/livingroom/temperature', 'myhome/ground$floor/+/temperature')thất bại
Jonathan Allan

Như Value Ink nói, +/kei$ha/+không phù hợp music/kei$ha/latest.
Chas Brown

1

Python 2 , 85 84 80 92 89 byte

lambda s,c:all(x in('+','#',y)for x,y in zip(c.split('/')+[0]*-c.find('#'),s.split('/')))

Hãy thử trực tuyến!

Cảm ơn Jonathan AllanValue Ink đã chỉ ra lỗi.


Đưa ra câu trả lời sai trên f('ab', 'abc').
Mực giá trị

@Jonathan Allan: Trên thực tế, các quy tắc nói 'Số lượng trường chủ đề> = số trường tiêu chí'. Nhưng các vấn đề khác cần khắc phục ...
Chas Brown

Oh quy tắc kỳ lạ đưa ra bối cảnh vấn đề!
Jonathan Allan

1

Haskell, 76 73 71 67 byte

(a:b)#(c:d)=a=='+'&&b#snd(span(/='/')d)||a=='#'||a==c&&b#d
a#b=a==b

Hãy thử trực tuyến!

Chỉnh sửa: -4 byte nhờ @cole.


1
a#b=a==bdường như hoạt động với một vài byte ít hơn, trừ khi tôi thiếu một cái gì đó
cole

@cole: vâng, nó hoạt động. Cảm ơn rất nhiều!
nimi

1

Clojure , 107 91 76 65 102 byte

Một hàm ẩn danh, trả về chủ đề chủ đề là trung thực và nilnhư falsey (hợp lệ trong Clojure).

(defn ?[t c](every? #(#{"#""+"(% 0)}(% 1))(apply #(map vector % %2)(map #(re-seq #"[^/]+" %) [t c]))))

107 102 làm việc
91 76 65 tất cả bị đánh bại với ký tự regex


... và nhận xét của tôi dưới câu hỏi của bạn trở nên thích hợp
Jonathan Allan

@Jonathan ALLan, thực sự, ngoại trừ + và # không xuất hiện trong chuỗi chủ đề chủ đề :)
Patrick

Tôi nghĩ rằng điều này không thành công cho chủ đề music/kei$ha/latestvà tiêu chí +/kei$ha/+(phải phù hợp và là ASCII hợp lệ).
Chas Brown

@ChasBrown, chính xác và với ^ thay vì $; cảm ơn.
Patrick

1
Hãy thử với '\ Q' trước và '\ E' sau mẫu trước nguồn
Jonathan Allan


0

Python 3, 99 88 byte

Không sử dụng regex. Với sự giúp đỡ của Jonathan Allan và Chas Brown.

f=lambda s,p:p in(s,'#')or p[:1]in(s[:1],'+')and f(s[1:],p['+'!=p[:1]or(s[:1]in'/')*2:])

f=lambda s,p:s==p or'#'==p[0]or p[0]in(s[0]+'+')and f(s[1:],p['+'!=p[0]or(s[0]=='/')*2:])lưu 12. Tuy nhiên, điều này không thể xử lý một số trường hợp cạnh như f('abc/ijk/x', 'abc/+/xyz')hoặc f('abc/ijk/xyz', 'abc/+/x'), có thể được khắc phục bằngf=lambda s,p:s==p or'#'==p[:1]or p[:1]in(s[:1]+'+')and f(s[1:],p['+'!=p[:1]or(s[:1]=='/')*2:])
Jonathan Allan

Điều này không thành công f('abc','ab')f('abc/de','abc')(cả hai nên quay lại False, nhưng thay vào đó là một IndexError).
Chas Brown

...or p[:1]in(s[:1],'+')and...sửa các trường hợp cạnh @ChasBrown và tôi đã chỉ ra chi phí là 2 byte.
Jonathan Allan

Thất bại một trường hợp cạnh khác của dấu '+' (ví dụ f('a/b', 'a/+')) nhưng có thể sửa trong 0 byte bằng ...or(s[:1]in'/')*2:]).
Jonathan Allan

Hãy thử trực tuyến luôn luôn được khuyến khích!
Chas Brown

0

Than , 36 byte

≔⪪S/θ≔⪪S/ηF∧№η#⊟η≔…θLηθF⌕Aη+§≔θι+⁼θη

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Đầu ra -( Đầu ra ngầm định của Char than true) cho một trận đấu, không có gì cho không khớp. Giải trình:

≔⪪S/θ

Tách đối tượng trên /s.

≔⪪S/η

Chia các tiêu chí trên /s.

F∧№η#⊟η≔…θLηθ

Nếu tiêu chí chứa (nghĩa là kết thúc bằng) a #thì hãy xóa nó và cắt đối tượng theo độ dài mới của tiêu chí.

F⌕Aη+§≔θι+

Trường hợp tiêu chí chứa +sau đó thay thế phần tử đó trong chủ đề bằng +.

⁼θη

So sánh đối tượng với các tiêu chí và ngầm in kết quả.


0

Võng mạc 0.8.2 , 42 byte

%`$
/
+`^([^/]+/)(.*¶)(\1|\+/)
$2
^¶$|¶#/$

Hãy thử trực tuyến! Giải trình:

%`$
/

Hậu tố a /đến cả hai dòng.

+`^([^/]+/)(.*¶)(\1|\+/)
$2

Liên tục loại bỏ yếu tố đầu tiên của cả chủ đề và tiêu chí trong khi chúng bằng nhau hoặc yếu tố tiêu chí là một (hạnh phúc) +.

^¶$|¶#/$

Các tiêu chí phù hợp nếu nó chỉ là một #(với /cái đã được thêm vào trước đó) nếu không cả chủ đề và tiêu chí sẽ bị trống vào thời điểm này.




0

JavaScript, 69 66 byte

t=>s=>new RegExp(s.split`+`.join`[^/]+`.split`#`.join`.+`).test(t)

Hãy thử trực tuyến!


Điều này không thành công cho chủ đề music/kei$ha/latestvà tiêu chí +/kei$ha/+(phải phù hợp và là ASCII hợp lệ).
Chas Brown


0

05AB1E , 21 byte

ε'/¡}ζʒ'+å≠}˜'#¡н2ôøË

Nhập dưới dạng một danh sách theo thứ tự [criteria, topic].

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

ε                      # Map both strings in the implicit input-list to:
 '/¡                  '#  Split the string on "/"
                       #   i.e. ["+/+/A/B/#","z/y/A/B/x/w/v/u"]
                       #    → [["+","+","A","B","#"],["z","y","A","B","x","w","v","u"]]
                     # After the map: zip/transpose the two string-lists,
                       # with space as (default) filler
                       #  → [["+","z"],["+","y"],["A","A"],["B","B"],["#","x"],[" ","w"],
                       #     [" ","v"],[" ","u"]]
      ʒ    }           # Filter each pair by:
       '+å≠           '#  Only keep those which do NOT contain a "+"
                       #   → [["A","A"],["B","B"],["#","x"],[" ","w"],[" ","v"],[" ","u"]]
            ˜          # Flatten the filtered list
                       #  → ["A","A","B","B","#","x"," ","w"," ","v"," ","u"]
             '#¡      '# Split the list by "#"
                       #  → [["A","A","B","B"],["x"," ","w"," ","v"," ","u"]]
                н      # Only keep the first part
                       #  → ["A","A","B","B"]
                 2ô    # Split this back into pairs of two
                       #  → [["A","A"],["B","B"]]
                   ø   # Zip/transpose them back
                       #  → [["A","B"],["A","B"]]
                    Ë  # And check if both inner lists are equal
                       #  → 1 (truthy)
                       # (after which the result is output implicitly)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.