Đếm sự thật


59

Lấy cảm hứng từ, và trong ký ức của người bạn và đồng nghiệp thân yêu của tôi,

Nam tước Dan

Dan Baronet , 1956 - 2016. RIP

Ông tìm thấy giải pháp APL ngắn nhất có thể cho nhiệm vụ này:

Bài tập, nhiệm vụ

Đưa ra một danh sách Boolean, đếm số lượng giá trị chân lý.

Ví dụ trường hợp

{}0

{0}0

{1}1

{0, 1, 1, 0, 0}0

{1, 1, 1, 0, 1}1

{1, 1, 0, 1, 1}2

{0, 0, 1, 1, 1}3

{1, 1, 1, 1, 1, 1}6


Chúng ta có thể lấy danh sách dưới dạng một chuỗi số không và số không? ví dụ 01100?
Ad Nam

@Adnan chỉ khi đó là cách bình thường nhất để ngôn ngữ của bạn đại diện cho danh sách boolean.
Adám

71
Lấy làm tiếc về mất mát của bạn.
Martin Ender

6
@MartinEnder Cảm ơn bạn. Nó sẽ khó khăn đi về phía trước. Dan đã dạy tôi tất cả những gì tôi cần biết để làm việc cho Dyalog.
Adám

5
Vĩnh biệt Đàn. RIP ...
Erik the Outgolfer 7/11/2016

Câu trả lời:


36

APL Dyalog, 6 2 byte

⊥⍨

Kiểm tra nó trên TryAPL .

Làm thế nào nó hoạt động

(uptack, cặp đôi: decode) thực hiện chuyển đổi cơ sở. Nếu toán hạng bên trái là một vectơ, nó thực hiện chuyển đổi cơ sở hỗn hợp , hoàn hảo cho nhiệm vụ này.

Với một vectơ cơ sở b = b n , ⋯, b 0 và một vectơ chữ số a = a n ,, a 0 , b ⊥ a chuyển đổi a thành cơ sở hỗn hợp b , tức là, nó tính b 0 b n - 1 a n + ⋯ + b 0 b 1 a 2 + b 0 a 1 + a 0 .

Bây giờ, (dieresis dấu ngã, đi lại) sẽ thay đổi người vận hành bên trái như sau. Trong một bối cảnh đơn điệu, nó gọi toán tử với các đối số trái và phải bằng nhau.

Ví dụ, ⊥⍨ một được định nghĩa là một ⊥ một , mà tính một 0 ⋯ một n + ⋯ + a 0 một 1 một 2 + a 0 một 1 + a 0 , tổng của tất cả các sản phẩm tích lũy từ bên phải sang bên trái .

Đối với k trailing, k sản phẩm ngoài cùng bên phải là 1 và tất cả các sản phẩm khác là 0 , vì vậy tổng của chúng bằng k .


14
Gợi ý: Dan đã làm điều đó chỉ trong hai byte.
Adám

3
Chuyển đổi cơ sở hỗn hợp! Thật khéo léo.
Dennis

1
Oh. Chuyển đổi cơ sở hỗn hợp, làm thế nào nó đình công một lần nữa.
Conor O'Brien

Bravo! Trong thực tế, vì Dan, chúng tôi đặc biệt b⊥b⊥⍨btừ bỏ để tăng tốc vô hạn.
Adám

19

JavaScript (ES6), 21 byte

f=l=>l.pop()?f(l)+1:0

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


Cái này hoạt động ra sao? Làm thế nào để f(l)+1trả về một giá trị > 2?
Oliver

@Oliver Đây là một quá trình đệ quy, được đánh giá là l.pop()?(l.pop()?(l.pop()?(...etc...)+1:0)+1:0)+1:0.
Arnauld

Tôi hiểu rồi. Cảm ơn đã giải thích.
Oliver

11

Thạch , 4 byte

ŒrṪP

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

Đối với trường hợp danh sách trống, có một số quan sát tò mò. Đầu tiên, mã hóa chiều dài chạy danh sách trống []trả về một danh sách trống khác []. Sau đó, lấy lại phần tử cuối cùng từ đó bằng cách sử dụng trả về đuôi 0thay vì một cặp [value, count]là các phần tử thông thường của mảng được mã hóa theo chiều dài chạy. Sau đó, sản phẩm Ptrả về 0khi được gọi 0là kết quả mong đợi.

Giải trình

ŒrṪP  Main link. Input: list M
Œr    Run-length encode
  Ṫ   Tail, get the last value
   P  Product, multiply the values together

Ngoài ra, ŒgṪScông trình, quá!
Lynn

Nó cung cấp đầu ra đúng cho danh sách trống làm đầu vào, nhưng tôi ngạc nhiên khi đưa ra cách phân tích. Bạn có phiền khi đi qua trường hợp đặc biệt đó không?
Peter Taylor

@PeterTaylor Tôi cũng ngạc nhiên vì nó hoạt động. Ngoài ra, tôi chỉ nhận thấy rằng liên kết đầu tiên có mã sai.
dặm

@PeterTaylor trong Jelly được triển khai như : lambda z: iterable(z).pop() if iterable(z) else 0. iterablekhi được gọi trong danh sách chỉ cần trả về danh sách, và danh sách trống dĩ nhiên là giả.
FryAmTheEggman

10

Brachylog , 7 6 5 byte

@]#=+

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

Giải trình

@]        A suffix of the Input...
  #=      ...whose elements are all equal
    +     Sum its elements

@] - Suffixbắt đầu từ hậu tố lớn nhất cho đến nhỏ nhất, nên nó sẽ tìm thấy lần chạy dài nhất trước tiên.



10

Haskell, 26 25 byte

a%b|b=1+a|0<3=0
foldl(%)0

Sử dụng:

Prelude> foldl(%)0 [True,False,True,True]
2

Phiên bản Pointfree (26 byte):

length.fst.span id.reverse

Sử dụng danh sách số nguyên thay vì danh sách bool (21 byte, nhờ Christian Sievers):

a%b=b*(a+1)
foldl(%)0

Sử dụng:

Prelude> foldl(%)0 [1,0,1,1]
2

Phiên bản miễn phí (25 byte)

sum.fst.span(==1).reverse

Đối với danh sách số nguyên, foldlý tưởng hoạt động vớia%b=b*(a+1)
Christian Sievers

9

Võng mạc , 7 5 byte

r`1\G

Hãy thử trực tuyến! (Dòng đầu tiên cho phép bộ kiểm tra được phân tách bằng nguồn cấp.)

Xác định định dạng đầu vào cho Retina không hoàn toàn rõ ràng. Vì Retina không có khái niệm về bất kỳ loại nào ngoại trừ các chuỗi (và cũng không có giá trị nào có thể được sử dụng cho định nghĩa thông thường của chúng ta về sự thật và giả), nên tôi thường sử dụng 01(hoặc một cái gì đó tích cực nói chung) để tương ứng với sự thật và giả dối, vì chúng đại diện không hoặc một số trận đấu, tương ứng.

Với các cách biểu thị một ký tự, chúng ta cũng không cần một dấu phân cách cho danh sách (theo một cách nào đó, là biểu diễn danh sách tự nhiên hơn cho một ngôn ngữ chỉ có chuỗi). Adám xác nhận rằng đây là một định dạng đầu vào chấp nhận được.

Đối với bản thân regex, nó khớp từ right sang trái và \Gneo từng trận đấu với cái trước đó. Do đó, điều này tính có bao nhiêu 1s chúng ta có thể khớp từ cuối chuỗi.


"Có, đối với Retina, vì nó chỉ xử lý các chuỗi, tôi nghĩ rằng chuỗi" 01 "hoặc" FT "theo thứ tự.
Adám

9

05AB1E , 12 10 6 5 byte

Đã lưu 1 byte nhờ tính toán carusocomputing .

Î0¡¤g

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

Giải trình

Î      # push 0 and input
 0¡    # split on 0
   ¤   # take last item in list
    g  # get length

0¡¤glà bốn byte.
Bạch tuộc ma thuật Urn

@carusocomputing: Đẹp quá! Vẫn chưa được làm rõ nếu đầu vào chuỗi có ổn không khi tôi viết bài này, nhưng tôi thấy bây giờ nó là :)
Emigna

J0¡¤gvẫn còn ngắn hơn;).
Bạch tuộc ma thuật Urn

@carusocomputing: Thật không may, chúng tôi cần Îxử lý đầu vào trống, nhưng đó vẫn là một byte được lưu cảm ơn :)
Emigna




7

Toán học, 25 24 byte

Fold[If[#2,#+1,0]&,0,#]&

3
Chỉ cần ghi lại một cổng của giải pháp cơ sở hỗn hợp mát mẻ của Dan: FromDigits[b=Boole@#,MixedRadix@b]&(35 byte).
Greg Martin


5

C90 (gcc), 46 byte

r;main(c,v)int**v;{while(0<--c&*v[c])r++;c=r;}

Đầu vào là thông qua các đối số dòng lệnh (một số nguyên cho mỗi đối số), đầu ra thông qua mã thoát .

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

Làm thế nào nó hoạt động

r là một biến toàn cục. Kiểu của nó mặc định là int và, là toàn cục, nó có giá trị mặc định là 0 .

Đối số hàm c mặc định là int . Nó sẽ giữ số nguyên n + 1 cho các mảng của n Booleans; đối số đầu tiên của chính luôn là đường dẫn của tệp thực thi.

Đối số hàm v được khai báo là int**. Loại v thực tế sẽ là char**, nhưng vì chúng ta sẽ chỉ kiểm tra bit có ý nghĩa nhỏ nhất của mỗi đối số để phân biệt các ký tự 0 (mã điểm 48 ) và 1 (mã điểm 49 ) máy móc.

Vòng lặp while giảm c và so sánh nó với 0 . Khi c đạt 0 , chúng ta sẽ thoát ra khỏi vòng lặp. Điều này chỉ cần thiết nếu mảng không chứa 0 's.

Chừng nào 0<--ctrở về 1 , chúng tôi sẽ đưa các c th đối số dòng lệnh ( v[c]) và trích xuất ký tự đầu tiên của mình với bởi dereferencing con trỏ ( *). Chúng ta lấy bit AND của Boolean 0<--cvà điểm mã của ký tự (và ba byte rác theo sau nó), do đó điều kiện sẽ trả về 0 khi gặp 0 , thoát khỏi vòng lặp.

Trong trường hợp còn lại, trong khi các đối số dòng lệnh là 1 , r++tăng r lên 1 , do đó đếm số lượng theo dõi 1 's.

Cuối cùng, c=rlưu trữ giá trị tính toán của r trong c . Với các thiết lập mặc định, trình biên dịch tối ưu hóa và loại bỏ gán; nó thực sự tạo ra movl %eax, -4(%rbp)hướng dẫn. Vì rettrả về giá trị của thanh ghi EAX, điều này tạo ra đầu ra mong muốn.

Lưu ý rằng mã này không hoạt động với C99, trả về 0 từ chính nếu đạt đến cuối của chính .


argcít nhất là 1(có argv[0]chứa tên tệp) không? Bạn có thể lưu một byte với --c&&thay vì 0<--c&. Mã thoát gcc hè được lấy từ argcđâu? Khéo léo.
Tít

@Titus Điều đó sẽ không làm việc. *v[c]là điểm mã của 1 hoặc 0 , vì vậy nó là 49 hoặc 48 và do đó luôn luôn đúng.
Dennis

Với C89 và C90, gcc trả về bất cứ thứ gì có trong RAX tại thời điểm đó. C99 luôn trả về 0 từ chính nếu kết thúc đạt được.
Dennis

4

k, 6 byte

+/&\|:

Hàm hợp này dịch để sum mins reverseq, của ngôn ngữ anh chị em dễ đọc hơn, nơi phút là tối thiểu lăn.


Có thể: bị rơi?
streetster

4

J, 9 3 byte

#.~

Đây là phản xạ chuyển đổi cơ sở hỗn hợp. Bởi vì điều này giống như chuyển đổi cơ sở hỗn hợp. Lần nữa.

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

   v =: #.~
   ]t =: '';0;1;0 1 1 0 0;1 1 1 0 1;1 1 0 1 1;0 0 1 1 1;1 1 1 1 1 1
++-+-+---------+---------+---------+---------+-----------+
||0|1|0 1 1 0 0|1 1 1 0 1|1 1 0 1 1|0 0 1 1 1|1 1 1 1 1 1|
++-+-+---------+---------+---------+---------+-----------+
   v&.> t
+-+-+-+-+-+-+-+-+
|0|0|1|0|1|2|3|6|
+-+-+-+-+-+-+-+-+
   (,. v&.>) t
+-----------+-+
|           |0|
+-----------+-+
|0          |0|
+-----------+-+
|1          |1|
+-----------+-+
|0 1 1 0 0  |0|
+-----------+-+
|1 1 1 0 1  |1|
+-----------+-+
|1 1 0 1 1  |2|
+-----------+-+
|0 0 1 1 1  |3|
+-----------+-+
|1 1 1 1 1 1|6|
+-----------+-+

2
Gợi ý: Điều này có thể được thực hiện chỉ trong 3 byte, sử dụng bản dịch J của giải pháp Dan.
Adám

1
@ Adám Tôi đã cố gắng tìm kiếm một giải pháp. Không nghĩ đến chuyển đổi cơ sở. Điều đó thực sự khá thông minh của anh ấy!
Conor O'Brien

1
Đúng. Đó là Dan. :-(
Adám

4

R, 40 39 25 byte

Giải pháp hoàn toàn được làm lại nhờ @Dason

sum(cumprod(rev(scan())))

Đọc đầu vào từ stdin, đảo ngược vectơ và nếu phần tử đầu tiên !=0sau đó xuất độ dài đầu tiên của mã hóa độ dài chạy ( rle), thì khác 0.


1
Bạn có thể lưu một byte bằng cách thay đổi dòng thứ hai thành ifelse(r$v,r$l,0)[1]. (Vectorized if, và sau đó lấy phần tử đầu tiên.)
rturnbull 6/11/2016

1
không cần iflelse - chỉ cần nhân r $ v và r $ l.
Dason

Nhưng tuyến tổng (cumprod (rev (.))) Sẽ tiết kiệm được rất nhiều byte dù sao đi nữa
Dason

3

Haskell, 24 byte

foldl(\a b->sum[a+1|b])0

Lặp lại danh sách, thêm một cho mỗi phần tử, đặt lại 0sau khi nó chạm a False.

16 byte với đầu vào 0/1:

foldl((*).(+1))0

Nếu danh sách được đảm bảo không trống, chúng tôi có thể nhận được 14 byte:

sum.scanr1(*)1

Điều này tính toán sản phẩm tích lũy từ phía sau, sau đó tính tổng chúng. Sản phẩm tích lũy duy trì 1 cho đến khi 0 bị tấn công và sau đó trở thành 0. Vì vậy, số 1 tương ứng với dấu 1.



3

C # 6, 103 72 byte

using System.Linq;
int a(bool[] l)=>l.Reverse().TakeWhile(x=>x).Count();

Sử dụng danh sách không chung chung đánh bại danh sách chung bằng 1 byte lol

-31 byte nhờ Scott


Nếu bạn sử dụng một mảng ints, bạn có thể thoát khỏiint a(int[] l)=>l.Reverse().TakeWhile(i=>i>0).Sum();
Scott

@Scott Tất nhiên những gì tôi đã nghĩ ... mặc dù vậy tôi sẽ gắn bó với bool. Câu hỏi chỉ định danh sách boolean và không phải C.
Liên kết Ng

Biên dịch thành a Func<bool[], int>cho 57 byte tức làusing System.Linq;l=>l.Reverse().TakeWhile(x=>x).Count();
TheLethalCoder

2

Python, 37 byte

f=lambda l:len(l)and-~f(l[:-1])*l[-1]

2

DASH , 16 byte

@len mstr"1+$"#0

Đây không phải là giải pháp DASH ngắn nhất có thể, nhưng giải pháp DASH ngắn nhất có thể đang làm tôi thất vọng. Tôi đang đăng cách tiếp cận tiểu thuyết này ở vị trí của nó.

Sử dụng:

(@len mstr"1+$"#0)"100111"

Giải trình

@(                 #. Lambda
  len (            #. Get the length of the array after...
    mstr "1+$" #0  #. ... matching the argument with regex /1+$/
  )                #. * mstr returns an empty array for no matches
)

2

Scala, 25 byte

l=>l.reverse:+0 indexOf 0

Ung dung:

l=>(l.reverse :+ 0).indexOf(0)

Đảo ngược danh sách, nối thêm 0 và tìm chỉ số đầu tiên là 0, là số phần tử trước 0 đầu tiên


2

Mẻ, 57 byte

@set n=0
@for %%n in (%*)do @set/an=n*%%n+%%n
@echo %n%

Lấy đầu vào là tham số dòng lệnh. Hoạt động bằng cách nhân bộ tích lũy với giá trị hiện tại trước khi thêm nó vào, để bất kỳ số 0 nào trong dòng lệnh đặt lại số đếm. Lưu ý rằng %%nkhông giống như nhoặc %n%biến.



2

Java 7, 62 byte

int c(boolean[]a){int r=0;for(boolean b:a)r=b?r+1:0;return r;}

Mã thử nghiệm & mã hóa:

Hãy thử nó ở đây.

class M{
  static int c(boolean[] a){
    int r = 0;
    for (boolean b : a){
      r = b ? r+1 : 0;
    }
    return r;
  }

  public static void main(String[] a){
    System.out.print(c(new boolean[]{}) + ", ");
    System.out.print(c(new boolean[]{ false }) + ", ");
    System.out.print(c(new boolean[]{ true }) + ", ");
    System.out.print(c(new boolean[]{ false, true, true, false, false }) + ", ");
    System.out.print(c(new boolean[]{ true, true, true, false, true }) + ", ");
    System.out.print(c(new boolean[]{ true, true, false, true, true }) + ", ");
    System.out.print(c(new boolean[]{ false, false, true, true, true }) + ", ");
    System.out.print(c(new boolean[]{ true, true, true, true, true, true }));
  }
}

Đầu ra:

0, 0, 1, 0, 1, 2, 3, 6

2

Perl 5.10, 22 byte

21 byte + 1 byte cho -acờ. Vì biểu thức dựa trên regex đã được thực hiện ...: p

Các giá trị đầu vào cho mảng phải được phân tách bằng khoảng trắng.

$n++while pop@F;say$n

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


1
Ngắn hơn một chút nếu bạn lấy các đối số thông qua dòng lệnh: perl -E '$_++while pop;say' 0 1 1 0 1 1 1nhưng điều này không tạo ra bất cứ điều gì cho 0(dù không chắc đó có phải là vấn đề hay không!)
Dom Hastings

2

Perl, 22 byte

21 byte mã + 1 byte cho -pcờ.

s/.(?=.*0)//g;$_=y;1;

Để chạy nó:

perl -pE 's/.(?=.*0)//g;$_=y;1;' <<< "0 1 1 0 1 1 1"

(Trên thực tế, định dạng của các đầu vào không quan trọng rất nhiều: 0110111, 0 1 1 0 1 1 1, [0,1,1,0,1,1,1]vv sẽ tất cả công việc)


Phiên bản 18 byte từ @Dom Hastings nhưng nó yêu cầu cung cấp đầu vào dưới dạng chuỗi 0 và 1, không được phép:

perl -pE '/1*$/;$_=length$&' <<< '0110111'

Yêu thích ;mánh khóe đó :) Nếu định dạng là một chuỗi liên tục: perl -pE '/1*$/;$_=length$&' <<< '0110111'trong 18, không chắc đó có phải là bẻ cong quy tắc hay không ...
Dom Hastings

@DomHastings yea, tôi cũng vậy! (Cảm ơn Ton đã cho tôi thấy điều đó!) Nhận xét đầu tiên và thứ hai của câu hỏi không cho phép định dạng đầu vào bạn cần cho giải pháp của bạn ... Nhưng tôi sẽ chỉnh sửa bài đăng của tôi để đề xuất phiên bản của bạn nếu định dạng của đầu vào nhiều hơn miễn phí.
Dada

2

PHP, 50 byte

<?=strlen(preg_filter('/.*[^1]/','',join($argv)));

Điều kỳ lạ là lần thử đầu tiên của tôi với regex hóa ra ngắn hơn lần thử của tôi với mảng ...
Sử dụng như:

php tt.php 1 1 0 1 1

2

Ruby 37 32 byte

->n{n.size-1-(n.rindex(!0)||-1)}

Tạo một hàm ẩn danh tìm thấy hầu hết các giá trị sai của giá trị sai và đếm kích thước của phân đoạn bắt đầu từ giá trị đó.

Nó sử dụng !0là false, vì 0 là các giá trị trung thực trong Ruby.rindextìm chỉ số cuối cùng của một giá trị trong một mảng.

Cách sử dụng :

boolean_list = [true, false, false, true]
->n{n.size-1-(n.rindex(!0)||-1)}[boolean_list]

Trả về 1


Nếu tôi được phép truyền một chuỗi 0 và 1 dưới dạng tham số dòng lệnh (đó không phải là cách ruby ​​đại diện cho danh sách booleans), tôi có thể giảm xuống còn 24:

$*[0]=~/(1*)\z/;p$1.size

Điều này sử dụng các biểu thức chính quy và in độ dài của chuỗi được trả về bởi biểu thức chính quy /(1*)\z/, ở đó \zlà phần cuối của chuỗi. $*[0]là đối số đầu tiên được thông qua và là một chuỗi 0 và 1.

Sử dụng:

trailing_truths.rb 011101

Trả về 1.


1
Khi bạn có chỉ mục của giá trị sai cuối cùng, tại sao bạn cần truy xuất lại các phần tử từ mảng?
Lee W

Bạn nói đúng, tôi không. Cảm ơn. Tắt 5 byte!
IMP1
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.