Phân tích một Đệ tứ


27

Nếu bạn chưa biết, thì một bộ tứ về cơ bản là một số gồm 4 phần. Đối với mục đích của thử thách này, nó có một thành phần thực và ba thành phần tưởng tượng . Các thành phần tưởng tượng được đại diện bởi các hậu tố i, j, k. Ví dụ, 1-2i+3j-4klà một quaternion với 1là thành phần thực tế và -2, 3-4là thành phần tưởng tượng.

Trong thử thách này, bạn phải phân tích dạng chuỗi của một bậc bốn (ví dụ "1+2i-3j-4k") thành một danh sách / mảng các hệ số (ví dụ [1 2 -3 -4]). Tuy nhiên, chuỗi bậc bốn có thể được định dạng theo nhiều cách khác nhau ...

  • Nó có thể là bình thường: 1+2i-3j-4k
  • Nó có thể thiếu các điều khoản : 1-3k, 2i-4k(Nếu bạn thiếu các điều khoản, đầu ra 0cho các điều khoản đó)
  • Nó có thể đã mất tích hệ số: i+j-k(Trong trường hợp này, điều này tương đương với 1i+1j-1kNói cách khác, a. i, jHoặc kkhông có một số ở phía trước được giả định có một 1trước theo mặc định)
  • Nó có thể không theo đúng thứ tự: 2i-1+3k-4j
  • Các hệ số có thể chỉ đơn giản là số nguyên hoặc số thập phân: 7-2.4i+3.75j-4.0k

Có một số điều cần lưu ý trong khi phân tích cú pháp:

  • Sẽ luôn có một +hoặc -giữa các điều khoản
  • Bạn sẽ luôn được thông qua đầu vào hợp lệ với ít nhất 1 thuật ngữ và không có chữ cái lặp lại (không có j-j)
  • Tất cả các số có thể được coi là hợp lệ
  • Bạn có thể thay đổi số sang loại hình khác sau khi phân tích cú pháp nếu bạn muốn (ví dụ. 3.0 => 3, 0.4 => .4, 7 => 7.0)

Phân tích cú pháp / quernion dựng và sơ hở tiêu chuẩn không được phép. Điều này bao gồm các evaltừ khóa và chức năng. Đầu vào sẽ là một chuỗi đơn và đầu ra sẽ là một danh sách, một mảng, các giá trị được phân tách bằng khoảng trắng, v.v.

Vì đây là , mã ngắn nhất tính bằng byte sẽ thắng.

Tấn thử nghiệm

1+2i+3j+4k             => [1 2 3 4]
-1+3i-3j+7k            => [-1 3 -3 7]
-1-4i-9j-2k            => [-1 -4 -9 -2]
17-16i-15j-14k         => [17 -16 -15 -14]

7+2i                   => [7 2 0 0]
2i-6k                  => [0 2 0 -6]
1-5j+2k                => [1 0 -5 2]
3+4i-9k                => [3 4 0 -9]

42i+j-k                => [0 42 1 -1]
6-2i+j-3k              => [6 -2 1 -3]
1+i+j+k                => [1 1 1 1]
-1-i-j-k               => [-1 -1 -1 -1]

16k-20j+2i-7           => [-7 2 -20 16]
i+4k-3j+2              => [2 1 -3 4]
5k-2i+9+3j             => [9 -2 3 5]
5k-2j+3                => [3 0 -2 5]

1.75-1.75i-1.75j-1.75k => [1.75 -1.75 -1.75 -1.75]
2.0j-3k+0.47i-13       => [-13 0.47 2.0 -3] or [-13 .47 2 -3]
5.6-3i                 => [5.6 -3 0 0]
k-7.6i                 => [0 -7.6 0 1]

0                      => [0 0 0 0]
0j+0k                  => [0 0 0 0]
-0j                    => [0 0 0 0] or [0 0 -0 0]
1-0k                   => [1 0 0 0] or [1 0 0 -0]

Sẽ có những +dấu hiệu không cần thiết trong đầu vào? Giống như : +1k?
FryAmTheEggman 30/03/2016

@FryAmTheEggman Số đầu vào sẽ không bao giờ bắt đầu bằng a +.
GamrCorps 30/03/2016

1
-0một phần của đầu ra hợp pháp cho hai ví dụ cuối cùng?
isaacg

1
@isaacg vâng, điều đó ổn thôi
GamrCorps 30/03/2016

1
@LLlAMnYP Bạn đưa ra một điểm tốt. Cho phép xác định các evalhạn chế được thực hiện trong một chuỗi, diễn giải dưới dạng mã và / hoặc đầu vào. Bất kỳ chuyển đổi nào không được tính theo điều này bởi vì bạn không thể vượt qua, ví dụ, chuỗi "test"thành hàm chuyển đổi số nguyên để nhận số nguyên, nhưng testsẽ được hiểu là mã trong một evalhàm bình thường . TLDR: eval: không, chuyển đổi loại: có.
GamrCorps 30/03/2016

Câu trả lời:


5

Bình thường, 48 byte

jm+Wg\-K--e|d0G\+K1+]-I#GJczfT.e*k<b\.zm/#dJ"ijk

Bộ thử nghiệm trình diễn

Các định dạng đầu ra được phân tách dòng mới. Mã bộ kiểm tra sử dụng phân tách không gian, để dễ đọc, nhưng mặt khác thì giống nhau.

Xuất ra một -0trong 2 trường hợp cuối cùng, mà tôi hy vọng là OK.

Giải thích để làm theo.


9

Võng mạc, 115

\b[ijk]
1$&
^(?!.*\d([+-]|$))
0+
^(?!.*i)
+0i+
^(?!.*j)
0j+
^(?!.*k)
0k+
O$`[+-]*[\d.]*(\w?)
$1
-
+-
^\+

S`[ijk+]+

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

Lưu 1 byte nhờ @Chris Jester-Young .

Đã sửa lỗi và lưu 6 byte nhờ @Martin Büttner

Tìm thấy một vài lỗi liên quan đến một số trường hợp cạnh, tăng số byte khá nhiều.

Trả về các dòng mới được phân tách. Dù sao, điều này có một giải pháp chủ yếu là thanh lịch bị phá hỏng bởi các trường hợp cạnh nhưng hey tôi phải sử dụng chế độ sắp xếp, điều đó có nghĩa là tôi đã sử dụng đúng công cụ cho công việc, phải không?

Giải trình:

Từng giai đoạn, như thường lệ.

\b[ijk]
1$&

Các ký tự duy nhất trong đầu vào có thể tạo ranh giới từ là -+.. Điều này có nghĩa là nếu chúng ta tìm thấy một ranh giới theo sau là một chữ cái, chúng ta có một ẩn 1mà chúng ta thêm vào với sự thay thế. $&là một từ đồng nghĩa với $0.

^(?!.*\d([+-]|$))
0+

Rất cảm ơn Martin vì cái này, cái này thêm vào ẩn 0cho phần thực nếu nó bị thiếu trong đầu vào. Chúng tôi đảm bảo rằng chúng tôi không thể tìm thấy một số được theo sau bởi dấu cộng hoặc dấu trừ hoặc cuối chuỗi. Tất cả các số phức sẽ có một chữ cái sau chúng.

^(?!.*i)
+0i+

Cả 3 giai đoạn tiếp theo đều khá giống nhau, loại bỏ những chữ cái mà chúng tác động. Tất cả trong số họ nhìn xem liệu chúng tôi không thể khớp với chữ cái và nếu chúng tôi không thể thêm một 0thuật ngữ cho nó. Lý do duy nhất icó thêm +trước đó là để ngăn giá trị thực không thể đọc được với ihệ số s, các số khác được phân tách bằng biến phức của chúng.

O$`[+-]*[\d.]*(\w?)
$1

Ah, phần thú vị. Điều này sử dụng giai đoạn sắp xếp mới, được biểu thị bằng Otrước khi phân tách tùy chọn backtick. Mẹo ở đây là lấy toàn bộ số theo sau bởi một ký tự từ, trong trường hợp này sẽ chỉ khớp với một trong số đó ijk. Tùy chọn khác được sử dụng là $nguyên nhân khiến giá trị được sử dụng để sắp xếp các kết quả khớp này là thay thế. Ở đây chúng tôi chỉ sử dụng chữ cái tùy chọn còn lại làm giá trị sắp xếp của chúng tôi. Vì Retina sắp xếp theo từ vựng theo mặc định, các giá trị được sắp xếp giống như trong từ điển, nghĩa là chúng ta có các kết quả khớp theo "", "i", "j", "k"thứ tự.

-
+-

Giai đoạn này đặt một +dấu hiệu trước tất cả các dấu trừ, điều này là cần thiết nếu chúng ta có một giá trị âm cho itrong giai đoạn phân chia, sau này.

^ \ +

Chúng tôi loại bỏ hàng đầu +để đảm bảo rằng chúng tôi không có thêm dòng mới hàng đầu.

S`[ijk+]+

Tách các dòng còn lại khi chạy các biến phức tạp hoặc dấu cộng. Điều này độc đáo cho chúng ta một giá trị trên mỗi dòng.


3

Perl 5, 125 byte

#!perl -p
%n=(h,0,i,0,j,0,k,0);$n{$4//h}=0+"$1@{[$3//$5//1]}"while/([+-]?)(([\d.]+)?([ijk])|([\d.]+))/g;s/.*/@n{qw(h i j k)}/

1
@KennyLau Đáng buồn thay, đề xuất thay đổi của bạn không làm những gì bạn mong đợi. Tôi đã thử điều đó trước khi tôi đăng câu trả lời của mình. ;-)
Chris Jester-Young

@KennyLau Về thay đổi được đề xuất này , các \atrận đấu của Perl trên "báo động", không phải là chữ cái. Có \wký tự từ (chữ và số và gạch dưới), nhưng điều đó sẽ không hoạt động ở đây; chúng ta cần nó không khớp với một số.
Chris Jester-Young

3
@KennyLau BTW, bạn có đủ đại diện để nói chuyện trong trò chuyện . Hãy thảo luận về các ý tưởng ở đó, thay vì liên tục nhận được các đề xuất chỉnh sửa của bạn bị từ chối. ;-)
Chris Jester-Young

Tôi cũng có đủ đại diện để bình luận bây giờ. Perl không có mẫu cho [az]?
Leaky Nun

1
@KennyLau Không theo hiểu biết của tôi.
Chris Jester-Young

3

Lua , 185 187 195 183 166 byte ( thử trực tuyến ) [regex đã sử dụng]

Cảm ơn @Chris Jester-Young vì regex được cải thiện.

Cảm ơn @Katenkyo đã đưa nó xuống 166 byte.

Chơi gôn

r={0,0,0,0}for u in(...):gsub("([+-])(%a)","%11%2"):gmatch("-?[%d.]+%a?")do n,i=u:match("(.+)(%a)")r[i and(" ijk"):find(i)or 1]=(n or u)end print(table.concat(r," "))

Ung dung:

n = "42i+j-k+0.7"

result = {0,0,0,0}

for unit in n:gsub("([+-])(%a)","%11%2"):gmatch("-?[%d.]+%a?") do
  num, index = unit:match("(.+)(%a)")
  if index == "i" then
    result[2] = num
  elseif index == "j" then
    result[3] = num
  elseif index == "k" then
    result[4] = num
  else
    result[1] = unit
  end
end

print(table.concat(result," "))

2
Xin chào Kenny, cảm ơn vì giải pháp. Thông thường chúng tôi không cho phép đầu vào bắt đầu bằng một biến (như ntrong trường hợp này), vì vậy bạn nên thêm mã để đọc đầu vào.
isaacg

Bạn sẽ có thể lưu một số byte bằng cách thay đổi đầu vào của bạn từ STDIN thành đối số, thay vì io.read()sử dụng (...). Nó sẽ trỏ đến đối số dòng lệnh đầu tiên và sẽ cho phép bạn lưu thêm 4 byte :)
Katenkyo 30/03/2016

1
Ngoài ra, đầu ra được hỏi có thể là bất cứ thứ gì, miễn là nó có thể được con người xen vào như một danh sách, vì vậy bạn có thể xóa định dạng bổ sung. Bao gồm một số khoảng trắng khác mà bạn có thể tắt, mã của bạn có thể giảm xuống 166 byte ->r={0,0,0,0}for u in(...):gsub("([+-])(%a)","%11%2"):gmatch("-?[%d.]+%a?")do n,i=u:match("(.+)(%a)")r[i and(" ijk"):find(i)or 1]=(n or u)end print(table.concat(r," "))
Katenkyo 30/03/2016

3

C, 236 byte

char j,n[9][9],s[9],y[9],i=8,k,*p=n[8];main(c){for(**n=48;c=getchar(),c+1;)c-32&&(c<46&&(k&&(y[1]=i),k=0,s[--i]=c-43,p=n[i])||c>57&&(k||(*p=49),k=0,y[c-103]=i)||(*p++=c,k=1));for(k&&(y[1]=i);++j<5;)printf("%c%s ",s[y[j]]?45:0,n[y[j]]);}

(Đối với các giá trị như -0 hoặc -0.0, dấu trừ cũng được in trong đầu ra, nhưng vì thách thức nói rằng "bạn có thể thay đổi số thành dạng khác sau khi phân tích cú pháp nếu bạn muốn" và nếu -0 xuất hiện trong đầu vào, theo sau nó cũng được chấp nhận trong đầu ra. @GamrCorps hiện đã làm rõ rằng điều này là ổn.)


3

JavaScript (ES6), 103 100 byte

f=s=>s.replace(/(?=.)(\+|-|)([\d.]*)(\w?)/g,(_,s,x,c)=>a[c.charCodeAt()&3]=+(s+(x||1)),a=[0,0,0,0])&&a

Chỉnh sửa: Đã lưu 3 byte bằng cách chuyển từ parseIntsang charCodeAt, thuận tiện chỉ cần &3lấy cho tôi chỉ số mảng chính xác.


Đẹp ý tưởng parseInt + mod. Suy nghĩ về cơ sở và tiền tố
edc65

1

JavaScript (ES6) 106

s=>(s.replace(/([+-]?)([\d.]*)(\w?)/g,(a,b,c,d)=>a&&(s[d||9]=b+(c||1)),s={}),[...'9ijk'].map(i=>+s[i]||0))

Kiểm tra

f=s=>(s.replace(/([+-]?)([\d.]*)(\w?)/g,(a,b,c,d)=>a&&(s[d||9]=b+(c||1)),s={}),[...'9ijk'].map(i=>+s[i]||0))

function Test()
{
  var t,k,r,ts=TS.value.split('\n')
  
  O.textContent=ts.map(x=>x.trim()&&(
    [t,k]=x.split('=>').map(x=>x.trim()),
    console.log(t,'*',k),
    k=k.match(/[\d+-.]+/g).map(x=>+x),
    r=f(t),
    t+' => '+r+(r+''==k+''?' OK':' KO (check: '+k+')')
  )).join('\n')
}    

Test()
#TS { width:90%; height:10em}
<pre id=O></pre>

Test data (modify if you like)<button onclick='Test()'>repeat test</button>
<textarea id=TS>
1+2i+3j+4k             => [1 2 3 4]
-1+3i-3j+7k            => [-1 3 -3 7]
-1-4i-9j-2k            => [-1 -4 -9 -2]
17-16i-15j-14k         => [17 -16 -15 -14]
  
7+2i                   => [7 2 0 0]
2i-6k                  => [0 2 0 -6]
1-5j+2k                => [1 0 -5 2]
3+4i-9k                => [3 4 0 -9]
  
42i+j-k                => [0 42 1 -1]
6-2i+j-3k              => [6 -2 1 -3]
1+i+j+k                => [1 1 1 1]
-1-i-j-k               => [-1 -1 -1 -1]
  
16k-20j+2i-7           => [-7 2 -20 16]
i+4k-3j+2              => [2 1 -3 4]
5k-2i+9+3j             => [9 -2 3 5]
5k-2j+3                => [3 0 -2 5]
  
1.75-1.75i-1.75j-1.75k => [1.75 -1.75 -1.75 -1.75]
2.0j-3k+0.47i-13       => [-13 0.47 2.0 -3]
5.6-3i                 => [5.6 -3 0 0]
k-7.6i                 => [0 -7.6 0 1]
  
0                      => [0 0 0 0]
0j+0k                  => [0 0 0 0]
-0j                    => [0 0 0 0]
1-0k                   => [1 0 0 0]
</textarea>


0

PowerShell, 178 byte

param($a);$p="(-?)([\d.]+)?";$g={param($s)if($a-match"$p$s"){if(($r=$matches)[2]){$r[1]+$r[2]}else{$r[1]+1}}else{0}};$a-match"$p(\+|-|$)">$null;+$matches[2];"i","j","k"|%{&$g $_}

Ung dung với lời giải thích

# Get the whole string into a variable
param($a)
# Pattern shared getting both imaginary and real numbers. 
$p="(-?)([\d.]+)?"
# Anonymous function that will locate a imaginary number using a letter sent as a parameter. 
# If no value is assigned a signed 1 is returned. If no value is matched 0 is returned
$g={param($s)if($a-match"$p$s"){if(($r=$matches)[2]){$r[1]+$r[2]}else{$r[1]+1}}else{0}}
# Locate the real component if any. Null is converted to 0
$a-match"$p(\+|-|$)">$null;+$matches[2]
# Call the anonymous function using each of the imaginary suffixes.                                               
"i","j","k"|%{&$g $_}

Không siêu ấn tượng nhưng dù sao nó cũng là một kết quả.


0

PHP, 179 byte

$a=[''=>0,'i'=> 0,'j'=>0,'k'=>0];preg_match_all("/([-+]?)(\d*(\.\d+)?)([ijk]?)/",$argv[1],$m,2);foreach($m as$n)if($n[0])$a[$n[4]]=$n[1].($n[2]===''?1:$n[2]);echo implode(',',$a);

Hãy thử bộ thử nghiệm .


0

Python 3.5 - 496 byte [sử dụng Biểu thức chính quy]:

from re import*
def wq(r):
 a=sub('[+](?![0-9])','+1',sub('[-](?![0-9])','-1',r));q=lambda x:(not x.isdigit(),''.join(filter(str.isalpha,x)))
 for z in findall('(?<![0-9])[a-z]',a):a=a.replace(z,('+1{}'.format(z)))
 if not str(sorted(((sub('[.]','',sub('[+-]',' ',a))).split(' ')),key=q)[0]).isdigit():a+='+0, '
 for i in list(set(findall('[a-z]',a))^{'i','j','k'}):a+='+0{}, '.format(i)
 print(findall('[-]?\d+(?:\.\d+)?',''.join(sorted(sub('(?<=[A-Za-z0-9])(?=[+-])',', ',a).split(' '),key=q))))

Nó có thể dài, nhưng để bảo vệ tôi, nó hoạt động hoàn hảo trong việc thực hiện những gì OP muốn, vì tất cả các trường hợp thử nghiệm được đưa ra đều thành công khi sử dụng mã của tôi.

Phiên bản Ungolfed với lời giải thích bao gồm:

from re import*
def w(r):
    # Substitute all minus (-) and plus (+) signs NOT followed by a number  (if there are any) with a "-1"/"+1", respectively.
    a=sub('[+](?![0-9])','+1',sub('[-](?![0-9])','-1',r))
    # Lambda function created for later use to sort the Quaternion. This function, when given as a key to the "sorted" function, arranges the input Quaternion in the order where the whole number comes first, and then the rest are placed in order of increasing letter value (i,j,k in this case) 
    q=lambda x:(not x.isdigit(),''.join(filter(str.isalpha,x)))
    # The following "for" loop replaces the letters NOT preceded by a number with a one followed by that letter
    for z in findall('(?<![0-9])[a-z]',a):
        a=a.replace(z,('+1{}'.format(z)))
    # The following first substitutes all pluses and minuses (+ and -) with a space, and then that new string is split at those spaces, and returned as a list. After that, the list is sorted according the the "lambda" function shown above. Then, the first item in that list, which is supposed to be a lone number, is checked to make sure that it indeed is a lone number. If it isn't, then "+0, " is appended to the Quaternion. 
    if not str(sorted(((sub('[.]','',sub('[+-]',' ',a))).split(' ')),key=q)[0]).isdigit():
        a+='+0, '
    # The following "for" loop finds ALL the letters NOT in the list, by finding the symmetric difference between a set of all the letters found, and a set containing all the letters needed. For the letters not in the list, a '+0' is added the quaternion, followed by that letter, and then a comma and a space.
    for i in list(set(findall('[a-z]',a))^{'i','j','k'}):
        a+='+0{}, '.format(i)
    # Finally, in this last step, a ", " is added IN BETWEEN unicode characters and pluses/minuses (+/-). Then, it splits at those spaces, and the commas separate different parts of the Quaternion from each other (otherwise, you would get something like `12i+3j+4k` from `2i+3j+4k+1`) in a returned list. Then, that list is sorted according to the lambda expression "q" (above), and then, finally, the NUMBERS (of any type, courtesy to Regex) are extracted from that joined list, and printed out in the correct order.
    print(findall('[-]?\d+(?:\.\d+)?',''.join(sorted(sub('(?<=[A-Za-z0-9])(?=[+-])',', ',a).split(' '),key=q))))

Nếu ở trên là một chút quá khó để đọc, về cơ bản những gì đang xảy ra là:

  1. Nếu có bất kỳ, tất cả các dấu + hoặc - KHÔNG được theo sau bởi một số được thay thế bằng "+1" / "- 1", tương ứng.

  2. Một lambdahàm được định nghĩa, khi được sử dụng trong một sortedhàm làm khóa, sắp xếp danh sách theo cách đặt toàn bộ số trước, sau đó sắp xếp phần còn lại để tăng giá trị chữ cái ("i", sau đó "j", sau đó "k" trong trường hợp này).

  3. Đệ tứ, hiện có tất cả các dấu +/- được thay thế bằng 1 nếu cần, được tìm kiếm, sử dụng Biểu thức chính quy, cho TẤT CẢ các chữ cái KHÔNG có trước ít nhất một số và các chữ cái đó được thay thế bằng "+1" theo sau lá thư đó

  4. Câu lệnh "if" sau đó thay thế TẤT CẢ các dấu +/- bằng một khoảng trắng, và sau đó Quancyion đã sửa đổi hiện được "phân tách" tại các khoảng trắng đó và được trả về trong một danh sách. Sau đó, danh sách được sắp xếp theo chức năng lambda đã giải thích trước đó. Cuối cùng, mục đầu tiên trong danh sách đó được kiểm tra để đảm bảo đó là một số, vì nó phải là, và nếu không, thì "+0" sẽ được thêm vào Đệ tứ.

  5. Vòng lặp "for" thứ hai tìm thấy TẤT CẢ các chữ cái KHÔNG trong Đệ tứ bằng cách tìm sự khác biệt đối xứng giữa một tập hợp các chữ cái được tìm thấy trong biểu thức và sau đó là một tập hợp bao gồm tất cả các chữ cái được yêu cầu. Nếu tìm thấy bất kỳ, thì "+0" theo sau là chữ cái bị thiếu và một khoảng trắng được thêm vào Đệ tứ.

  6. Cuối cùng, trong bước cuối cùng này, một "," được thêm vào giữa mỗi ký tự theo sau là ký hiệu +/- và sau đó Quancyion được phân chia tại các khoảng trắng đó, sau đó, danh sách được trả về được sắp xếp, lần cuối cùng, theo danh sách Hàm lambda được định nghĩa là "q" trước đó. Dấu phẩy trong biểu thức tách biệt từng phần của tứ phân vị (nếu không, bạn sẽ nhận được một cái gì đó giống như 14i+5j+6ktừ 4i+5j+6k+1). Cuối cùng, danh sách đã được sắp xếp đó được nối với nhau thành một chuỗi và chỉ các số thuộc bất kỳ loại nào (lịch sự của Biểu thức chính quy) được trích xuất và cuối cùng được trả về trong một danh sách, theo đúng thứ tự, mỗi lần.

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.