Làm thế nào tôi có thể ghép vớ từ một đống hiệu quả?


3912

Hôm qua tôi đã đi đôi tất từ ​​đồ giặt sạch và nhận ra cách tôi đang làm nó không hiệu quả lắm. Tôi đang thực hiện một tìm kiếm ngây thơ - chọn một chiếc tất và "lặp lại" đống đồ để tìm cặp của nó. Điều này đòi hỏi phải lặp đi lặp lại trên n / 2 * n / 4 = n 2/8 vớ trung bình.

Là một nhà khoa học máy tính, tôi đã nghĩ mình có thể làm gì? Sắp xếp (theo kích thước / màu sắc / ...) tất nhiên xuất hiện để đạt được giải pháp O (NlogN).

Băm hoặc các giải pháp không tại chỗ khác không phải là một lựa chọn, vì tôi không thể sao chép tất của mình (mặc dù nó có thể tốt nếu tôi có thể).

Vì vậy, câu hỏi về cơ bản là:

Cho một đống nvớ, có chứa 2ncác yếu tố (giả sử mỗi chiếc tất có chính xác một đôi phù hợp), cách tốt nhất để ghép chúng hiệu quả với không gian thêm vào logarit là gì? (Tôi tin rằng tôi có thể nhớ lượng thông tin đó nếu cần.)

Tôi sẽ đánh giá cao một câu trả lời giải quyết các khía cạnh sau đây:

  • Một giải pháp lý thuyết chung cho một số lượng lớn vớ.
  • Số lượng vớ thực tế không nhiều, tôi không tin người phối ngẫu của mình và tôi có hơn 30 đôi. (Và khá dễ để phân biệt giữa tất của tôi và của cô ấy; nó có thể được sử dụng không?)
  • Có tương đương với vấn đề phân biệt yếu tố ?

448
Tôi sử dụng nguyên tắc lỗ chim bồ câu để ghép chính xác một cái từ đống đồ giặt. Tôi có 3 màu vớ khác nhau (Đỏ, Xanh lam và Xanh lục) và 2 đôi mỗi màu. Tôi nhặt được 4 số vớ mỗi lần và tôi luôn tạo một đôi và đi làm.
Srinivas

59
Một nguyên tắc lỗ chim bồ câu khác: nếu bạn có một tập hợp con của n / 2 +1, thì phải có ít nhất một đôi trong tập hợp con này.
wildplasser

40
Câu hỏi tuyệt vời! Bạn có thể quan tâm đến bài viết của tôi về một vấn đề liên quan, đó là một cuộc thảo luận về xác suất kéo hai chiếc vớ phù hợp ra khỏi đống: blog.msdn.com/b/ericlippert/archive/2010/03/22/iêu
Eric Lippert

336
Tại sao không sinh ra một đứa trẻ và waitpidvì vậy, với tư cách là cha mẹ, bạn thậm chí không tự mình sắp xếp bất kỳ chiếc vớ nào?
Mxyk

137
Tôi đã giải quyết vấn đề này bằng cách chỉ sở hữu những đôi tất cao đến đầu gối màu trắng. Tất cả đều phù hợp. Tôi chỉ đơn giản có thể lấy bất kỳ hai chiếc vớ ngẫu nhiên từ đống và chúng sẽ khớp với nhau. Tôi tiếp tục đơn giản hóa vấn đề bằng cách KHÔNG đi tất. Tôi có một ngăn kéo vớ mà tôi chỉ đơn giản là ném tất cả vào, không ghép đôi. Tôi lấy hai cái ngẫu nhiên từ ngăn kéo mỗi sáng. Tôi đã đơn giản hóa nó thành O (0). Không thể đơn giản hơn thế. :)
Lee

Câu trả lời:


2450

Các giải pháp sắp xếp đã được đề xuất, nhưng sắp xếp hơi quá nhiều : Chúng tôi không cần trật tự; chúng ta chỉ cần các nhóm bình đẳng .

Vì vậy, băm sẽ là đủ (và nhanh hơn).

  1. Đối với mỗi màu của vớ, tạo thành một đống . Lặp lại tất cả các vớ trong giỏ đầu vào của bạn và phân phối chúng vào các cọc màu .
  2. Lặp lại qua từng cọc và phân phối nó theo một số liệu khác (ví dụ mẫu) vào nhóm cọc thứ hai
  3. Áp dụng đệ quy sơ đồ này cho đến khi bạn phân phối tất cả các cọc lên các cọc rất nhỏ mà bạn có thể xử lý trực quan ngay lập tức

Kiểu phân vùng băm đệ quy này thực sự đang được SQL Server thực hiện khi nó cần băm nối hoặc băm tổng hợp trên các tập dữ liệu khổng lồ. Nó phân phối luồng đầu vào xây dựng của nó thành nhiều phân vùng độc lập. Sơ đồ này chia tỷ lệ theo số lượng dữ liệu tùy ý và nhiều CPU theo tuyến tính.

Bạn không cần phân vùng đệ quy nếu bạn có thể tìm thấy khóa phân phối (khóa băm) cung cấp đủ các nhóm mà mỗi nhóm đủ nhỏ để được xử lý rất nhanh. Thật không may, tôi không nghĩ rằng vớ có một tài sản như vậy.

Nếu mỗi chiếc tất có một số nguyên gọi là "PairID", người ta có thể dễ dàng phân phối chúng thành 10 thùng theo PairID % 10(chữ số cuối cùng).

Phân vùng trong thế giới thực tốt nhất mà tôi có thể nghĩ đến là tạo ra một hình chữ nhật của các cọc : một chiều là màu sắc, chiều kia là hoa văn. Tại sao một hình chữ nhật? Bởi vì chúng ta cần O (1) truy cập ngẫu nhiên vào các cọc. (Một hình khối 3D cũng sẽ hoạt động, nhưng điều đó không thực tế lắm.)


Cập nhật:

Thế còn song song ? Nhiều người có thể phù hợp với vớ nhanh hơn?

  1. Chiến lược song song đơn giản nhất là có nhiều công nhân lấy từ giỏ đầu vào và đặt tất lên các cọc. Điều này chỉ tăng quy mô rất nhiều - hãy tưởng tượng 100 người chiến đấu trên 10 cọc. Các chi phí đồng bộ hóa (biểu hiện là va chạm tay và giao tiếp với con người) phá hủy hiệu quả và tăng tốc (xem Luật Khả năng mở rộng toàn cầu !). Đây có phải là dễ bị bế tắc ? Không, bởi vì mỗi công nhân chỉ cần truy cập một đống tại một thời điểm. Chỉ với một "khóa", không thể có bế tắc. Livelocks có thể có thể tùy thuộc vào cách con người phối hợp truy cập vào cọc. Họ có thể chỉ sử dụng backoff ngẫu nhiêngiống như các card mạng làm điều đó ở mức vật lý để xác định card nào có thể độc quyền truy cập vào dây mạng. Nếu nó hoạt động cho các NIC , nó cũng hoạt động cho cả con người.
  2. Nó quy mô gần như vô thời hạn nếu mỗi công nhân có bộ cọc riêng . Công nhân sau đó có thể lấy một lượng lớn vớ từ giỏ đầu vào (rất ít tranh chấp vì họ hiếm khi làm điều đó) và họ không cần phải đồng bộ hóa khi phân phối tất cả (vì chúng có các cọc cục bộ). Cuối cùng, tất cả các công nhân cần liên minh các bộ cọc của họ. Tôi tin rằng có thể được thực hiện trong O (log (số công nhân * cọc trên mỗi công nhân)) nếu các công nhân tạo thành một cây tổng hợp .

Còn vấn đề phân biệt yếu tố thì sao? Như bài viết nêu, vấn đề khác biệt yếu tố có thể được giải quyết trong O(N). Điều này cũng tương tự đối với vấn đề vớ (cũng vậy O(N), nếu bạn chỉ cần một bước phân phối (tôi đã đề xuất nhiều bước chỉ vì con người rất tệ trong tính toán - một bước là đủ nếu bạn phân phối md5(color, length, pattern, ...), tức là một hàm băm hoàn hảo của tất cả các thuộc tính)).

Rõ ràng, người ta không thể đi nhanh hơn O(N), vì vậy chúng tôi đã đạt đến giới hạn dưới tối ưu .

Mặc dù các kết quả đầu ra không hoàn toàn giống nhau (trong một trường hợp, chỉ là một boolean. Trong trường hợp khác, các đôi vớ), các phức tạp tiệm cận là như nhau.


72
Đây chính xác là những gì tôi làm! Tôi tạo các cọc phụ thuộc vào kiểu mở của tất (tôi chỉ có màu trắng), điều đó mang lại cho tôi đủ "xô" để nhanh chóng khớp với từng cái đó.
Scott Chamberlain

30
Tôi đã thử điều này với tất của mình (tôi đã có dễ dàng hơn 30 đôi) và người đàn ông đó là NHANH CHÓNG. Một vấn đề tôi đã tìm thấy là khi tôi không thể có một thuật toán băm đủ tốt (tôi đã có rất nhiều vớ trắng mà không có bất kỳ mẫu nào) nên nó trở nên khó khăn. Trong trường hợp đó, cách tối ưu để làm điều đó là gì?
NothingsImpossible

56
@NothingsImpossible Có thể đó là cách các cuộc tấn công va chạm băm cảm thấy như thế nào đối với một máy chủ web nghèo! Là vớ trắng phân biệt bởi một số thuộc tính? Phải có một cái gì đó bạn có thể phân phối chúng trên. Nếu không, bạn chỉ có thể tạo thành các cặp tùy ý.
usr

37
Đây là một sắp xếp Radix, mà tôi đồng ý là câu trả lời đúng. @MarkPeter Tôi không nghĩ bạn cần một bảng tra cứu. Một đường truyền tuyến tính duy nhất trên tất có thể chuyển đổi vớ thành vectơ số, làm cho việc ánh xạ "phân đoạn sock" thành xô tầm thường. Các vớ có thể được buộc vào các vectơ bằng chuỗi để bạn không cần một đường truyền tuyến tính khác ở cuối.
Mũi nhọn

49
Một anh chàng tôi đã đi học đại học với thực sự có PairID. Nó được may trên mỗi đôi vớ bằng chỉ: 1, 2, 3, 4 ...
Ryan Lundy

579

Vì kiến ​​trúc của bộ não con người hoàn toàn khác so với CPU hiện đại, câu hỏi này không có ý nghĩa thực tế.

Con người có thể chiến thắng các thuật toán CPU bằng cách sử dụng thực tế rằng "tìm một cặp phù hợp" có thể là một thao tác cho một bộ không quá lớn.

Thuật toán của tôi:

spread_all_socks_on_flat_surface();
while (socks_left_on_a_surface()) {
     // Thanks to human visual SIMD, this is one, quick operation.
     pair = notice_any_matching_pair();
     remove_socks_pair_from_surface(pair);
}

Ít nhất đây là những gì tôi đang sử dụng trong cuộc sống thực, và tôi thấy nó rất hiệu quả. Nhược điểm là nó đòi hỏi một bề mặt phẳng, nhưng nó thường rất phong phú.


229
khi số lượng vớ tăng lên, SIMD của con người trở nên không tốt hơn CPU.
Lie Ryan

25
Câu trả lời tốt nhất, IMO. Mặc dù thật thú vị và thông minh (và phù hợp với SO) để giảm bớt vấn đề hàng ngày đối với thuật toán máy tính, nhưng sẽ hợp lý hơn khi sử dụng sức mạnh phân giải của mắt / não của con người cho một bộ nhỏ tới 60 vớ.
thuốc_user841417

13
@LieRyan Nếu tất được phân phối đồng đều, cuối cùng bạn sẽ nhận thấy một đôi trong bất kỳ bộ vớ nào đủ nhỏ do nghịch lý sinh nhật (trừ khi bạn có thể phân biệt màu sắc với độ chính xác tùy ý, mà tôi nghi ngờ) vì vậy nút thắt ở đây sẽ không thuật toán kết hợp màu của con người nhưng bước lan rộng.
Thomas

13
@ dpc.ucore.info Không, bởi vì chúng có các mẫu còng dệt khác nhau, chiều dài còng, chiều dài tổng thể và màu đen (vợ tôi có thể sẽ làm tổn thương tôi về cái cuối cùng).
Christian

200
Bạn có hy vọng tốt hơn là bạn có số lượng vớ chẵn, nếu không bạn sẽ gấp tất trong một thời gian dài ...
Patrick James McDougle

258

Trường hợp 1 : Tất cả các vớ đều giống hệt nhau (đây là những gì tôi làm trong cuộc sống thực).

Chọn bất kỳ hai trong số họ để làm cho một cặp. Thời gian không đổi.

Trường hợp 2 : Có một số lượng kết hợp không đổi (quyền sở hữu, màu sắc, kích thước, kết cấu, v.v.).

Sử dụng sắp xếp cơ số . Đây chỉ là thời gian tuyến tính vì không cần phải so sánh.

Trường hợp 3 : Số lượng kết hợp không được biết trước (trường hợp chung).

Chúng ta phải so sánh để kiểm tra xem hai chiếc vớ có đi đôi không. Chọn một trong nhữngO(n log n) thuật toán sắp xếp dựa trên so sánh.

Tuy nhiên, trong cuộc sống thực khi số lượng vớ tương đối nhỏ (không đổi), các thuật toán tối ưu về mặt lý thuyết này sẽ không hoạt động tốt. Nó có thể mất nhiều thời gian hơn so với tìm kiếm tuần tự, về mặt lý thuyết đòi hỏi thời gian bậc hai.


8
> Nó có thể mất nhiều thời gian hơn so với tìm kiếm tuần tự, đòi hỏi thời gian bậc hai trong lý thuyết. Vâng đó là lý do tại sao tôi ghét làm điều này, có lẽ tôi nên vứt bỏ tất của mình và bắt đầu với trường hợp 1.
Nils

57
mặt trái của việc có tất cả các loại vớ giống hệt nhau là chúng có xu hướng già đi ở các tỷ lệ khác nhau. Vì vậy, cuối cùng bạn vẫn cố gắng kết hợp chúng dựa trên mức độ mòn của chúng. (khó hơn so với khớp đơn giản theo mẫu)
SDC

118
Vấn đề với việc có 60 đôi vớ giống hệt nhau "bởi vì nó giúp việc ghép đôi dễ dàng hơn" là nó mang lại cho mọi người ấn tượng khi bạn làm việc với máy tính.
Steve Ives

13
Trường hợp 1 không phải là thời gian không đổi khi có một hoạt động liên quan, chẳng hạn như các cặp gấp lại với nhau. Trong trường hợp này, đó là thời gian tuyến tính với hệ số không đổi nhỏ nhất (bằng chứng về phần còn lại là bài tập cho người đọc). Người ta không thể mất cùng lúc gấp một đôi và một xô đầy tất. Tuy nhiên, nó quy mô tuyến tính. Theo luật của Amdahl, nó có khả năng tăng tốc không giới hạn, bỏ qua chi phí hoạt động. Theo luật của Gustafson, bạn có thể gấp bao nhiêu cặp khi cần gấp một cặp cho đủ công nhân (số lượng còn lại là một bài tập cho người đọc), bỏ qua chi phí.
acelent

7
@PauloMadeira Việc sắp xếp là thời gian không đổi - bạn chỉ cần lấy đống và đặt nó vào ngăn kéo của bạn. Hoạt động duy nhất trong trường hợp này là thực sự đặt tất vào chân bạn cũng không đổi. Hiệu suất đạt được bằng cách thực hiện trì hoãn việc mang tất, có thể với một số hy sinh trong không gian (không gian tiêu thụ của tất không gấp lớn hơn gấp lại). Tôi cho rằng điều này là xứng đáng; Tôi thường thua cuộc cãi vã này với vợ.
Travis

157

Câu trả lời không thuật toán, nhưng "hiệu quả" khi tôi làm điều đó:

  • bước 1) loại bỏ tất cả các vớ hiện có của bạn

  • bước 2) đến Walmart và mua chúng bằng các gói 10 - n gói màu trắng và m gói màu đen. Không cần màu sắc khác trong cuộc sống hàng ngày.

Đôi khi, tôi phải làm điều này một lần nữa (mất tất, mất tất, v.v.) và tôi ghét phải loại bỏ những đôi tất hoàn toàn tốt quá thường xuyên (và tôi ước họ tiếp tục bán cùng một tham chiếu vớ!), Vì vậy gần đây tôi đã lấy Một cách tiếp cận khác.

Câu trả lời thuật toán:

Cân nhắc hơn nếu bạn chỉ rút một chiếc tất cho chồng vớ thứ hai, như bạn đang làm, khả năng bạn tìm được chiếc tất phù hợp trong một tìm kiếm ngây thơ là khá thấp.

  • Vì vậy, chọn năm trong số chúng một cách ngẫu nhiên, và ghi nhớ hình dạng hoặc chiều dài của chúng.

Tại sao năm? Thông thường con người rất tốt khi ghi nhớ từ năm đến bảy yếu tố khác nhau trong bộ nhớ làm việc - hơi giống với con người tương đương với ngăn xếp RPN - năm là một mặc định an toàn.

  • Nhặt một từ ngăn xếp 2n-5.

  • Bây giờ hãy tìm một kết hợp (khớp mẫu trực quan - con người rất giỏi với một ngăn xếp nhỏ) bên trong năm bạn đã vẽ, nếu bạn không tìm thấy một, sau đó thêm nó vào năm.

  • Giữ ngẫu nhiên chọn vớ từ ngăn xếp và so sánh với vớ 5 + 1 của bạn cho một trận đấu. Khi ngăn xếp của bạn phát triển, nó sẽ làm giảm hiệu suất của bạn nhưng tăng tỷ lệ cược của bạn. Nhanh hơn nhiều.

Hãy viết ra công thức để tính toán số lượng mẫu bạn phải rút ra cho tỷ lệ cược 50% của trận đấu. IIRC đó là một định luật siêu bội.

Tôi làm điều đó mỗi sáng và hiếm khi cần nhiều hơn ba lần rút - nhưng tôi có nnhững đôi tương tự (khoảng 10, cho hoặc lấy những cái bị mất) của mnhững chiếc vớ trắng có hình. Bây giờ bạn có thể ước tính kích thước của chồng cổ phiếu của tôi :-)

BTW , tôi thấy rằng tổng chi phí giao dịch của việc phân loại tất cả các lần mỗi khi tôi cần một đôi ít hơn nhiều so với thực hiện một lần và ràng buộc tất. Một thời gian hoạt động tốt hơn bởi vì sau đó bạn không phải buộc tất, và cũng có một lợi nhuận cận biên giảm dần (nghĩa là bạn tiếp tục tìm kiếm hai hoặc ba chiếc vớ đó khi ở đâu đó trong đồ giặt và bạn cần để kết thúc phù hợp với vớ của bạn và bạn mất thời gian về điều đó).


25
Upvote cho câu trả lời 'không thuật toán'. Đây chính xác là những gì tôi làm và nó hoạt động tuyệt vời. Vấn đề thay thế không phải là vấn đề nếu bạn 'xoay' cổ phiếu của bạn bằng cách đặt vớ đã rửa ở phía sau và kéo từ phía trước ngăn kéo vào buổi sáng. Tất cả các vớ đều nhau. Khi tôi bắt đầu nhận thấy một số mặc trên một, tôi đưa vào danh sách mua sắm để thay thế hoàn toàn toàn bộ lớp vớ đó. Đối với những đôi tất cũ, tôi dành 20% tốt nhất cho Thiện chí (được buộc trong túi tạp hóa để chúng không bị lẫn vào nhau) và ném phần còn lại. Bạn không lãng phí tất, tại thời điểm này, 80% chỉ còn 6 tháng nữa.
FastAl

2
BTW (1) Liên kết vớ của bạn dẫn đến một loại đàn hồi được lưu trữ kéo dài và sẽ thất bại nhanh hơn nhiều. Hạn chế các loại vớ độc đáo mà bạn có làm cho ràng buộc không bị che giấu. (2) Một nhược điểm của việc hạn chế những chiếc vớ độc đáo là đối với những người có mối quan tâm thời trang nhất định, phương pháp này có thể không phù hợp.
FastAl

3
Tôi đến đây đặc biệt để đăng câu trả lời "không thuật toán" của bạn. Như trong khoa học máy tính thực sự, hầu hết mọi người không bao giờ chú ý đến dữ liệu và cấu trúc của nó.
bkconrad

Tôi sử dụng phương pháp thuật toán này mỗi sáng và nó hoạt động như một bùa mê! Ngoài ra, tôi đã bỏ tất vào một đống khác để vứt đi sau đó (tiếc là họ đã xoay sở để lấy lại đống ban đầu trước khi tôi tìm thấy thời gian để vứt nó đi).
Donatas Olsevičius

3
«N gói màu trắng và m gói màu đen. Không cần màu sắc khác trong cuộc sống hàng ngày »Một quy tắc tiêu chuẩn tốt để lựa chọn sock dễ dàng thực sự là chúng phải phù hợp với màu quần của bạn hoặc màu của thắt lưng. Vì lý do này, các màu được sử dụng phổ biến nhất có thể sẽ là đen, xanh dương, xám và một số màu nâu. Thật khó tin người ta cần nhiều vớ trắng.
Andrea Lazzarotto

106

Những gì tôi làm là tôi nhặt chiếc tất đầu tiên và đặt nó xuống (giả sử, trên mép của bát giặt). Sau đó, tôi nhặt một chiếc tất khác và kiểm tra xem nó có giống với chiếc tất đầu tiên không. Nếu có, tôi loại bỏ cả hai. Nếu không, tôi đặt nó xuống bên cạnh chiếc tất đầu tiên. Sau đó, tôi nhặt chiếc tất thứ ba và so sánh nó với hai chiếc đầu tiên (nếu chúng vẫn ở đó). Vân vân.

Cách tiếp cận này có thể được thực hiện khá dễ dàng trong một mảng, giả sử rằng "loại bỏ" vớ là một lựa chọn.Trên thực tế, bạn thậm chí không cần phải "loại bỏ" vớ. Nếu bạn không cần phân loại vớ (xem bên dưới), thì bạn chỉ cần di chuyển chúng xung quanh và kết thúc với một mảng có tất cả các vớ được sắp xếp theo cặp trong mảng.

Giả sử rằng hoạt động duy nhất cho vớ là so sánh cho sự bằng nhau, thuật toán này về cơ bản vẫn là một n 2 thuật toán , mặc dù tôi không biết về trường hợp trung bình (chưa bao giờ học cách tính toán đó).

Sắp xếp, tất nhiên giúp cải thiện hiệu quả, đặc biệt là trong cuộc sống thực, nơi bạn có thể dễ dàng "nhét" một chiếc tất vào giữa hai chiếc vớ khác. Trong điện toán, cây cũng có thể đạt được điều tương tự, nhưng đó là không gian thừa. Và, tất nhiên, chúng tôi sẽ quay lại NlogN (hoặc hơn một chút, nếu có một vài chiếc vớ giống nhau bằng cách sắp xếp tiêu chí, nhưng không phải từ cùng một đôi).

Ngoài ra, tôi không thể nghĩ bất cứ điều gì, nhưng phương pháp này dường như khá hiệu quả trong cuộc sống thực. :)


7
Đây cũng là những gì tôi làm, (lưu ý rằng nếu bạn chỉ để lại khoảng trắng thì phần chèn cũng là O (1)), nhưng nó có tỷ lệ kém với số lượng lớn về mặt lý thuyết.
Vịt Mooing

15
quy mô kém với số lượng lớn các loại vớ
Steven Lu

@StevenLu - như tôi đã nói - đó là n * n hoặc nLogn, tùy thuộc vào việc bạn sắp xếp nó hay không. Vì vậy, nó quy mô kém như bất kỳ thuật toán sắp xếp. Nếu bạn muốn nhanh hơn, đánh số chúng và sử dụng sắp xếp cơ số.
Vilx-

Điều này về cơ bản là lưu trữ vớ tìm thấy nhưng không phù hợp trong tra cứu dựa trên hàm băm. Với một hàm băm lý tưởng, đó là O (n), nhưng nếu bạn đã lưu trữ tất đủ thì hàm băm bắt đầu thoái hóa, nó sẽ trở nên phức tạp hơn theo đó.
Jon Hanna

3
giá trị nào của việc chèn một chiếc tất giữa 2 chiếc vớ khác cung cấp cho mục tiêu ghép đôi vớ? không có cardinality của vớ. : -x
JoeBrockhaus

60

Đây là đặt câu hỏi sai. Câu hỏi đúng để hỏi là, tại sao tôi lại dành thời gian phân loại tất? Chi phí bao nhiêu trên cơ sở hàng năm, khi bạn định giá thời gian rảnh của mình cho các đơn vị tiền tệ X mà bạn chọn?

Và thường xuyên hơn không, đây không chỉ là bất kỳ thời gian rảnh nào , đó là thời gian rảnh buổi sáng , mà bạn có thể chi tiêu trên giường, hoặc nhâm nhi cà phê, hoặc để lại một chút sớm và không bị kẹt xe.

Thật tốt khi lùi lại một bước và suy nghĩ cách giải quyết vấn đề.

Và có một cách!

Tìm một chiếc tất bạn thích. Hãy tính đến tất cả các tính năng liên quan: màu sắc trong các điều kiện ánh sáng khác nhau, chất lượng và độ bền tổng thể, sự thoải mái trong các điều kiện khí hậu khác nhau và hấp thụ mùi. Điều quan trọng nữa là, chúng không nên làm mất tính đàn hồi trong bảo quản, vì vậy vải tự nhiên là tốt, và chúng nên có sẵn trong một gói nhựa.

Sẽ tốt hơn nếu không có sự khác biệt giữa vớ chân trái và chân phải, nhưng nó không quan trọng. Nếu vớ là đối xứng trái phải, tìm một đôi là hoạt động O (1) và sắp xếp vớ là hoạt động xấp xỉ O (M), trong đó M là số vị trí trong nhà bạn, nơi bạn đã xả rác bằng vớ, lý tưởng nhất là số không đổi nhỏ.

Nếu bạn chọn một đôi lạ mắt với các loại tất trái và phải khác nhau, thực hiện sắp xếp xô đầy đủ cho các xô chân trái và phải lấy O (N + M), trong đó N là số vớ và M giống như trên. Ai đó khác có thể đưa ra công thức cho các lần lặp trung bình của việc tìm cặp đầu tiên, nhưng trường hợp xấu nhất để tìm một cặp có tìm kiếm mù là N / 2 + 1, trở thành trường hợp không thể thiên văn cho hợp lý N. Điều này có thể được tăng tốc bằng cách sử dụng hình ảnh nâng cao thuật toán nhận dạng và chẩn đoán, khi quét đống vớ chưa phân loại bằng nhãn cầu Mk1 .

Vì vậy, một thuật toán để đạt được hiệu quả ghép sock O (1) (giả sử sock đối xứng) là:

  1. Bạn cần ước tính bạn sẽ cần bao nhiêu đôi vớ trong suốt quãng đời còn lại, hoặc có lẽ cho đến khi bạn nghỉ hưu và chuyển đến vùng khí hậu ấm áp hơn mà không cần phải đi tất nữa. Nếu bạn còn trẻ, bạn cũng có thể ước tính mất bao lâu trước khi tất cả chúng ta có robot phân loại sock trong nhà của chúng ta, và toàn bộ vấn đề trở nên không liên quan.

  2. Bạn cần tìm hiểu làm thế nào bạn có thể đặt hàng sock đã chọn với số lượng lớn và chi phí bao nhiêu và chúng có phân phối không.

  3. Đặt hàng vớ!

  4. Loại bỏ tất cũ của bạn.

Bước 3 thay thế sẽ liên quan đến việc so sánh chi phí mua cùng một số lượng vớ có lẽ rẻ hơn một vài đôi trong nhiều năm và thêm chi phí phân loại vớ, nhưng hãy lưu ý tôi: mua số lượng lớn rẻ hơn! Ngoài ra, vớ trong lưu trữ tăng giá trị theo tỷ lệ lạm phát giá cổ phiếu, nhiều hơn bạn sẽ nhận được trên nhiều khoản đầu tư. Sau đó, một lần nữa cũng có chi phí lưu trữ, nhưng tất thực sự không chiếm nhiều không gian trên kệ trên cùng của tủ quần áo.

Vấn đề được giải quyết. Vì vậy, chỉ cần có được những đôi tất mới, ném / tặng những chiếc cũ của bạn và sống hạnh phúc mãi mãi khi biết rằng bạn đang tiết kiệm tiền và thời gian mỗi ngày cho đến hết đời.


Cung cấp tất cả đời (giả sử 75 năm) (giả sử bạn xả hết 4 đôi / tháng, khiến 3600 đôi) sẽ mất (giả sử một đôi vớ mới chiếm 20 inch khối) tổng cộng 1 1/2 khối. Đó là một lượng không gian khổng lồ. Giả sử họ giao nó cho bạn trong một cái hộp gần bằng một khối lập phương, cái thùng đó sẽ dài khoảng 3 feet 4 inch ở một bên.
AJMansfield

2
@AJMansfield quan tâm hợp lệ. Tuy nhiên, tôi không đồng ý với một vài con số của bạn. Tôi sẽ mất một khoảng thời gian chỉ 40 năm (25 ... 65) (khoảng thời gian giữa không sống ở cha mẹ / ký túc xá / vv và nghỉ hưu, xem ở trên). Ngoài ra, tôi nghĩ rằng một cặp mất hơn 0,5x4x6 inch trong bao bì gốc. Những con số này mang lại không gian estime của bạn xuống khá nhiều!
hyde

Bước 4 là lãng phí không cần thiết, -1.
Dan Bechard

2
Hướng dẫn cho những người khác có thể bị nhầm lẫn bởi các phép đo của AJMansfield, một bản dịch sang số liệu: »sẽ mất (giả sử một đôi vớ mới chiếm 327 cm³) tổng cộng 1,14 m³. Đó là một lượng không gian khổng lồ. Giả sử họ giao nó cho bạn trong một cái hộp gần bằng một khối lập phương, cái thùng đó sẽ dài khoảng 1,04 m ở một bên. «
Joey

Làm thế nào một câu hỏi dựa trên sự tò mò có thể là "câu hỏi sai"? StackOverflow cổ điển ...
Timmmm

52

Giới hạn lý thuyết là O (n) vì bạn cần chạm vào từng chiếc tất (trừ khi một số đã được ghép nối bằng cách nào đó).

Bạn có thể đạt được O (n) với sắp xếp cơ số . Bạn chỉ cần chọn một số thuộc tính cho các thùng.

  1. Trước tiên, bạn có thể chọn (của cô ấy, của tôi) - chia chúng thành 2 đống,
  2. sau đó sử dụng màu sắc (có thể có bất kỳ thứ tự nào cho các màu, ví dụ theo thứ tự chữ cái theo tên màu) - chia chúng thành các đống theo màu (nhớ giữ thứ tự ban đầu từ bước 1 cho tất cả các vớ trong cùng một cọc),
  3. sau đó là chiều dài của tất,
  4. rồi kết cấu, ....

Nếu bạn có thể chọn số lượng thuộc tính giới hạn, nhưng đủ thuộc tính có thể xác định duy nhất từng cặp, bạn nên thực hiện trong O (k * n), đó là O (n) nếu chúng ta có thể coi k bị giới hạn.


3
Vớ thường có 4 gói và lớn hơn, vì giá rẻ hơn, nhưng điều đó cũng khiến chúng không thể phân biệt được. Để chống lại điều này, vợ tôi đã dán một dấu nhỏ lên mỗi đôi vớ mới tôi mua. Nhãn hiệu có màu khác nhau cho mỗi cặp hoặc có hình dạng khác nhau, nếu cô ấy hết màu. Với phương pháp này, bạn thậm chí không cần một bộ thuộc tính giới hạn. Chỉ cần may một số duy nhất trên mỗi cặp. :) Đối với các điểm thêm, sử dụng nhị phân.
Vilx-

29
@ Vilx- TẠI SAO?!? Không phải là toàn bộ vấn đề mà họ không thể phân biệt?
flup

2
@flup - Tôi nghĩ toàn bộ vấn đề là bán theo bó lớn hơn. :) Đối với tôi, điều này giúp làm giảm chúng theo cặp. Nếu không, tôi có thể kết thúc với ba chiếc vớ rất mòn và một chiếc mới. Kinda ngớ ngẩn.
Vilx-

13
Tôi không đồng ý với cách tính O (n). $ K $ là gì? $ k $ là số lượng thuộc tính. Tôi sẽ tranh luận $ k $ là $ O (log n) $ vì nó phải đủ để xác định duy nhất mỗi cặp. Nếu bạn có 2 cặp (đen và trắng), thì màu ($ k = 1, n = 2 $) là đủ. Nếu bạn có một cặp màu đen, ngắn; Một đôi màu đen, dài; Một đôi màu trắng, ngắn; và một cặp màu trắng, dài - sau đó $ k = 2, n = 4 $. Sau đó, nếu chúng tôi giới hạn $ k $, chúng tôi đồng thời giới hạn $ n $. Nếu chúng ta sẽ giới hạn $ n $ thì việc tính toán đơn hàng sẽ không còn ý nghĩa nữa.
emory

3
@emory, tôi nghĩ rằng bạn đang tìm kiếm backtick, không phải $nhân vật, để làm cho công cụ của bạn trông giống mã-y.
Xymostech

33

Là một giải pháp thiết thực:

  1. Nhanh chóng làm cho đống vớ dễ phân biệt. (Nói theo màu sắc)
  2. Quicksort mỗi cọc và sử dụng chiều dài của tất để so sánh. Là một con người, bạn có thể đưa ra một quyết định khá nhanh chóng để sử dụng để phân vùng để tránh trường hợp xấu nhất. (Bạn có thể thấy nhiều vớ song song, sử dụng điều đó cho lợi thế của bạn!)
  3. Dừng sắp xếp các cọc khi chúng đạt đến ngưỡng mà bạn cảm thấy thoải mái để tìm các cặp tại chỗ và vớ không thể mang theo ngay lập tức

Nếu bạn có 1000 vớ, với 8 màu và phân phối trung bình, bạn có thể tạo 4 cọc cho mỗi 125 vớ trong thời gian c * n. Với ngưỡng 5 vớ bạn có thể sắp xếp mỗi cọc trong 6 lần chạy. (Đếm 2 giây để ném một chiếc tất vào đúng cọc, bạn sẽ mất ít hơn 4 giờ.)

Nếu bạn chỉ có 60 vớ, 3 màu và 2 loại vớ (của bạn / vợ bạn), bạn có thể sắp xếp mỗi đống 10 vớ trong 1 lần chạy (Một lần nữa ngưỡng = 5). (Đếm 2 giây, bạn sẽ mất 2 phút).

Việc sắp xếp xô ban đầu sẽ tăng tốc quá trình của bạn, bởi vì nó phân chia n vớ của bạn thành k xô c*nkịp thời để bạn chỉ phải làm c*n*log(k)việc. (Không tính đến ngưỡng). Vì vậy, tất cả trong tất cả những gì bạn làm về n*c*(1 + log(k))công việc, trong đó c là thời gian để ném một chiếc tất lên một đống.

Cách tiếp cận này sẽ thuận lợi so với bất kỳ c*x*n + O(1)phương pháp nào chừng nào log(k) < x - 1.


Trong khoa học máy tính, điều này có thể hữu ích: Chúng tôi có một bộ sưu tập n thứ , một thứ tự về chúng (độ dài) và cũng có mối quan hệ tương đương (thông tin bổ sung, ví dụ màu của vớ). Mối quan hệ tương đương cho phép chúng tôi tạo một phân vùng của bộ sưu tập ban đầu và trong mọi lớp tương đương, thứ tự của chúng tôi vẫn được duy trì. Việc ánh xạ một thứ vào lớp tương đương của nó có thể được thực hiện trong O (1), do đó chỉ cần O (n) để gán từng mục cho một lớp. Bây giờ chúng tôi đã sử dụng thông tin bổ sung của mình và có thể tiến hành theo bất kỳ cách nào để sắp xếp mọi lớp. Ưu điểm là các bộ dữ liệu đã nhỏ hơn đáng kể.

Phương thức cũng có thể được lồng nhau, nếu chúng ta có nhiều quan hệ tương đương -> tạo các cọc màu, hơn trong mỗi phân vùng cọc trên kết cấu, hơn là sắp xếp theo chiều dài. Bất kỳ mối quan hệ tương đương nào tạo ra một phân vùng có nhiều hơn 2 phần tử có kích thước chẵn sẽ mang lại sự cải thiện tốc độ so với việc sắp xếp (với điều kiện chúng ta có thể gán trực tiếp một chiếc tất cho đống của nó) và việc sắp xếp có thể xảy ra rất nhanh trên các tập dữ liệu nhỏ hơn.


3
Tối ưu hóa con người: Tôi lập luận rằng với tư cách là một con người, ở bước 2, bạn nên sắp xếp các vớ xuống theo thứ tự tăng dần, sau đó lặp lại với độ chi tiết mịn hơn và mịn hơn cho đến khi được sắp xếp, giống như sắp xếp vỏ. Điều này sẽ nhanh hơn nhiều đối với con người (ước tính trực quan) so với cách tiếp cận dựa trên so sánh trao đổi.
AndrewC

28

Bạn đang cố gắng giải quyết vấn đề sai.

Giải pháp 1: Mỗi lần bạn bỏ tất bẩn vào giỏ giặt, hãy buộc chúng vào một nút nhỏ. Bằng cách đó, bạn sẽ không phải thực hiện bất kỳ phân loại nào sau khi giặt. Hãy nghĩ về nó giống như đăng ký một chỉ mục trong cơ sở dữ liệu Mongo. Một chút công việc phía trước cho một số tiết kiệm CPU trong tương lai.

Giải pháp 2: Nếu là mùa đông, bạn không cần phải đi tất phù hợp. Chúng tôi là lập trình viên. Không ai cần biết, miễn là nó hoạt động.

Giải pháp 3: Truyền bá công việc. Bạn muốn thực hiện quá trình CPU phức tạp như vậy một cách không đồng bộ, mà không chặn UI. Lấy đống vớ đó và nhét chúng vào một cái túi. Chỉ tìm một cặp khi bạn cần nó. Bằng cách đó, khối lượng công việc cần ít hơn đáng chú ý.

Hi vọng điêu nay co ich!


5
Buộc tất (hoặc bất kỳ quần áo nào) trong một nút thắt làm giảm khả năng của máy giặt để giặt quần áo, và làm cho việc cởi chúng trở nên khó khăn hơn nhiều. Giải pháp 2 làm cho việc bảo trì khó khăn hơn khi tình trạng tiến triển càng lâu; Sau 6 tháng, khi bạn cần hai chiếc vớ mắt cá chân màu đen để mặc cùng với một chiếc quần short và giày thể thao, 6 tháng làm bất cứ việc gì sẽ khiến việc tìm thấy đôi đó trong cùng một điều kiện (bẩn / sạch, mặc tương tự) ít có khả năng hơn. Giải pháp 3 ít "không đồng bộ" và "lười biếng" hơn; làm công việc tối thiểu bạn cần chính xác khi bạn cần.
KeithS

Re: giải pháp 2: Mọi người sẽ biết tôi không mang vớ phù hợp bởi vì họ sẽ nhìn thấy chúng trong Birks của tôi :)
Bob Probst

@BobProbst Có nhưng các lập trình viên đồng nghiệp của bạn cũng sẽ mang vớ vô song với Birks và do đó sẽ rất vui khi nhận thấy họ không phải là những người duy nhất.
Francesco Pasa

27

Câu hỏi này thực sự sâu sắc triết học. Thực chất là liệu sức mạnh của con người trong việc giải quyết vấn đề ("wetware" của bộ não của chúng ta) có tương đương với những gì có thể thực hiện được bằng thuật toán hay không.

Một thuật toán rõ ràng để sắp xếp sock là:

Let N be the set of socks that are still unpaired, initially empty
for each sock s taken from the dryer
  if s matches a sock t in N
    remove t from N, bundle s and t together, and throw them in the basket
  else
    add s to N

Bây giờ khoa học máy tính trong vấn đề này là tất cả về các bước

  1. "nếu s cặp với một sock t trong N". Làm thế nào nhanh chóng chúng ta có thể "nhớ" những gì chúng ta đã thấy cho đến nay?
  2. "Xóa t khỏi N" và "thêm s vào N". Làm thế nào đắt tiền là theo dõi những gì chúng ta đã thấy cho đến nay?

Con người sẽ sử dụng các chiến lược khác nhau để thực hiện những điều này. Bộ nhớ của con người liên kết , một cái gì đó giống như bảng băm trong đó các bộ tính năng của các giá trị được lưu trữ được ghép nối với chính các giá trị tương ứng. Ví dụ, khái niệm bản đồ "xe đỏ" cho tất cả những chiếc xe màu đỏ mà một người có khả năng ghi nhớ. Ai đó với một bộ nhớ hoàn hảo có một bản đồ hoàn hảo. Hầu hết mọi người không hoàn hảo về vấn đề này (và hầu hết những người khác). Bản đồ liên kết có một khả năng hạn chế. Ánh xạ có thể thổi ra khỏi sự tồn tại trong điều kiện khác nhau (một bia quá nhiều), được ghi do lỗi ( "Tôi mặc dù tên của bà là Betty, không Nettie"), hoặc không bao giờ được ghi đè mặc dù chúng tôi nhận thấy rằng sự thật đã thay đổi (" chiếc xe của cha "gợi lên" Firebird màu cam "khi chúng tôi thực sự biết rằng ông đã đổi nó lấy Camaro đỏ).

Trong trường hợp vớ, việc thu hồi hoàn hảo có nghĩa là nhìn vào một chiếc tất sluôn tạo ra bộ nhớ cho anh chị em của nó t, bao gồm đủ thông tin (nơi nó nằm trên bàn ủi) để xác định vị trí ttrong thời gian liên tục. Một người có trí nhớ chụp ảnh hoàn thành cả 1 và 2 trong thời gian liên tục mà không thất bại.

Ai đó có bộ nhớ kém hoàn hảo có thể sử dụng một vài lớp tương đương tương đương dựa trên các tính năng trong khả năng của mình để theo dõi: kích thước (papa, mama, em bé), màu sắc (xanh lục, đỏ, v.v.), mô hình (argyle, đồng bằng, v.v.) , phong cách (footie, cao đến đầu gối, vv). Vì vậy, bàn ủi sẽ được chia thành các phần cho các loại. Điều này thường cho phép danh mục được định vị theo thời gian không đổi theo bộ nhớ, nhưng sau đó cần tìm kiếm tuyến tính thông qua danh mục "nhóm".

Một người không có trí nhớ hoặc trí tưởng tượng nào cả (xin lỗi) sẽ chỉ giữ tất trong một đống và thực hiện tìm kiếm tuyến tính trên toàn bộ đống.

Một quái vật gọn gàng có thể sử dụng nhãn số cho các cặp như ai đó đề xuất. Điều này mở ra cơ hội cho tổng thứ tự, cho phép con người sử dụng chính xác các thuật toán giống như chúng ta có thể với CPU: tìm kiếm nhị phân, cây, băm, v.v.

Vì vậy, thuật toán "tốt nhất" phụ thuộc vào chất lượng của wetware / phần cứng / phần mềm đang chạy nó và chúng tôi sẵn sàng "gian lận" bằng cách áp đặt tổng số thứ tự cho các cặp. Chắc chắn một thuật toán meta "tốt nhất" là thuê người sắp xếp sock tốt nhất thế giới: một người hoặc máy có thể lưu trữ và nhanh chóng lưu trữ một bộ thuộc tính N của sock rất lớn trong bộ nhớ liên kết 1-1 với thời gian tra cứu, chèn, và xóa. Cả người và máy như thế này đều có thể mua được. Nếu bạn có một, bạn có thể ghép tất cả các vớ trong thời gian O (N) cho các cặp N, đó là tối ưu. Các thẻ tổng thứ tự cho phép bạn sử dụng băm tiêu chuẩn để có được kết quả tương tự với máy tính của con người hoặc phần cứng.


Ok, điều đó tốt hơn, mặc dù nó vẫn khá sai ... câu hỏi này không phải là về điều đó. Cho dù luận án Church-Turing có đúng hay không, cả con người và máy tính của chúng ta đều có thể phân loại vớ. (Thực tế là, con người, là những thực thể hữu hạn cao, có sức mạnh tính toán ít hơn nhiều so với Turing Machines ... và điều tương tự cũng đúng với máy tính của chúng ta, nhưng những hạn chế thì khác.)
Jim Balter

Tôi không đồng ý. Tất nhiên, bất kỳ máy tính hiện tại nào của chúng tôi về cơ bản là rất lớn và khác biệt về DFA (modulo i / o) chứ không phải là TM. Tuy nhiên, bất kỳ thiết bị tương tự nào, chẳng hạn như cơ thể của chúng ta, đều có khả năng mô phỏng một cuộn băng vô hạn. Chúng ta chưa có một đặc tính hữu ích về cách tính toán của tâm trí chúng ta.
Gene

Không có băng vô hạn cho con người hoặc các thiết bị vật lý khác vì không có gì trong não người có độ phân giải vô hạn, cũng không thể. Nó cũng sẽ giúp để tìm hiểu một số khoa học thần kinh. Trong mọi trường hợp, không có câu hỏi triết học sâu sắc ở đây, bất kể bạn muốn tiêm một cái. Nhưng hãy tin những gì bạn sẽ ... đây không phải là nơi cho cuộc tranh luận này và tôi đã có nó quá nhiều lần trước đây. Nhưng tôi luôn thích thú với những người hầu như không thể giải quyết những vấn đề đơn giản nhất (đó là tất cả chúng ta) tưởng tượng rằng chúng tương đương với TM.
Jim Balter

22

Chi phí: Di chuyển vớ -> cao, tìm / tìm vớ theo hàng -> nhỏ

Những gì chúng tôi muốn làm là giảm số lượng di chuyển, và bù đắp với số lượng tìm kiếm. Ngoài ra, chúng ta có thể sử dụng môi trường đa luồng của Homo Sapiens để chứa nhiều thứ hơn trong bộ đệm ẩn.

X = Yours, Y = Vợ / chồng của bạn

Từ đống A của tất cả các vớ:

Chọn hai vớ, đặt vớ X tương ứng vào dòng X và vớ Y ở dòng Y ở vị trí có sẵn tiếp theo.

Làm cho đến khi A trống.

Đối với mỗi dòng X và Y

  1. Chọn sock đầu tiên trong dòng, tìm kiếm dọc theo dòng cho đến khi tìm thấy sock tương ứng.

  2. Đặt vào dòng hoàn thành tương ứng của vớ.

  3. Tùy chọn Trong khi bạn đang tìm kiếm dòng và tất hiện tại bạn đang xem giống hệt với trước đó, hãy thực hiện bước 2 cho những đôi tất này.

Tùy chọn để bước một, bạn chọn hai sock từ dòng đó thay vì hai, vì bộ nhớ đệm đủ lớn để chúng ta có thể nhanh chóng xác định xem một trong hai sock có khớp với dòng hiện tại trên dòng bạn đang quan sát hay không. Nếu bạn may mắn có ba cánh tay, bạn có thể phân tích ba chiếc vớ cùng một lúc với điều kiện bộ nhớ của đối tượng đủ lớn.

Làm cho đến khi cả X và Y trống.

Làm xong

Tuy nhiên, vì điều này có độ phức tạp của simillar như sắp xếp lựa chọn, thời gian thực hiện ít hơn nhiều do tốc độ của I / O (vớ di chuyển) và tìm kiếm (tìm kiếm dòng cho một chiếc tất).


22

Đây là một Omega (n log n) ràng buộc thấp hơn trong mô hình dựa trên so sánh. (Hoạt động hợp lệ duy nhất là so sánh hai vớ.)

Giả sử bạn biết rằng vớ 2n của bạn được sắp xếp theo cách này:

p 1 p 2 p 3 ... p n p f (1) p f (2) ... p f (n)

trong đó f là một hoán vị chưa biết của tập {1,2, ..., n}. Biết điều này không thể làm cho vấn đề khó khăn hơn. Có n! kết quả đầu ra có thể (khớp giữa nửa đầu và nửa sau), có nghĩa là bạn cần so sánh log (n!) = Omega (n log n). Điều này có thể đạt được bằng cách sắp xếp.

Vì bạn quan tâm đến các kết nối với vấn đề phân biệt thành phần: việc chứng minh Omega (n log n) bị ràng buộc đối với tính khác biệt của phần tử khó hơn, bởi vì đầu ra là nhị phân có / không. Ở đây, đầu ra phải phù hợp và số lượng đầu ra có thể đủ để có một ràng buộc tốt. Tuy nhiên, có một biến thể kết nối với tính khác biệt của yếu tố. Giả sử bạn được tặng 2n vớ và tự hỏi liệu chúng có thể được ghép đôi độc đáo không. Bạn có thể nhận được giảm từ ED bằng cách gửi (a 1 , a 2 , ..., a n ) đến (a 1 , a 1 , a 2 , a 2 , ..., a n , a n ). (Về mặt khoa học, bằng chứng về độ cứng của ED rất thú vị, thông qua cấu trúc liên kết.)

Tôi nghĩ rằng nên có một Omega (n 2 ) ràng buộc cho vấn đề ban đầu nếu bạn chỉ cho phép kiểm tra công bằng. Trực giác của tôi là: Xem xét một biểu đồ nơi bạn thêm một cạnh sau khi kiểm tra và lập luận rằng nếu biểu đồ không dày đặc thì đầu ra không được xác định duy nhất.


19

Đây là cách tôi thực sự làm điều đó, đối với p đôi vớ ( n = 2p vớ riêng lẻ):

  • Lấy một chiếc tất ngẫu nhiên từ đống.
  • Đối với chiếc tất đầu tiên, hoặc nếu tất cả các đôi tất được chọn trước đó đã được ghép nối, chỉ cần đặt chiếc tất vào "khe" đầu tiên của một "mảng" của đôi tất không ghép trước mặt bạn.
  • Nếu bạn có một hoặc nhiều vớ không ghép đôi được chọn, hãy kiểm tra tất hiện tại của bạn với tất cả các vớ không ghép đôi trong mảng.
    • Có thể tách vớ thành các loại hoặc loại chung (trắng / đen, mắt cá chân / phi hành đoàn, thể thao / trang phục) khi xây dựng mảng của bạn và "đi sâu vào" để chỉ so sánh giống như muốn.
    • Nếu bạn tìm thấy một trận đấu chấp nhận được, đặt cả hai vớ lại với nhau và loại bỏ chúng khỏi mảng.
    • Nếu bạn không, đặt sock hiện tại vào khe mở đầu tiên trong mảng.
  • Lặp lại với mỗi chiếc tất.

Các kịch bản trường hợp xấu nhất của chương trình này là mỗi đôi vớ là đủ khác nhau mà nó phải phù hợp chính xác, và đó là người đầu tiên n / 2 vớ bạn chọn đều khác nhau. Đây là kịch bản O (n 2 ) của bạn và nó cực kỳ khó xảy ra. Nếu số loại sock t duy nhất ít hơn số lượng cặp p = n / 2 và tất trong mỗi loại là đủ như nhau (thường là về các thuật ngữ liên quan đến mặc) mà bất kỳ loại vớ nào có thể được ghép với bất kỳ khác, như tôi đã suy luận ở trên, số lượng vớ tối đa bạn sẽ phải so sánh là t , sau đó đôi tiếp theo bạn kéo sẽphù hợp với một trong những đôi tất không ghép đôi. Kịch bản này có nhiều khả năng trong ngăn kéo sock trung bình hơn trường hợp xấu nhất và giảm độ phức tạp của trường hợp xấu nhất thành O (n * t) trong đó thường là t << n .


1
Điều này có lẽ khá gần với quá trình tinh thần của tôi. Tôi có thêm một lớp tối ưu hóa sắp xếp trước. Vớ thể thao của tôi được giặt với người da trắng và vớ váy của tôi được rửa bằng màu sắc. Điều này có nghĩa là miễn là tôi không đổ hai đống đồ giặt cùng nhau, tất của tôi đã được nhóm theo loại. Tải màu trắng đi rất nhanh (nhiều vớ giống hệt nhau) nhưng vớ váy mất nhiều thời gian hơn. Khác mũi chìa khóa - làm cho nhiều bộ nhớ có sẵn cho các loại (gấp và loại bỏ tất cả các phi vớ đầu tiên và sau đó chạy các thuật toán cặp)
orh

17

Cách tiếp cận trong thế giới thực:

Càng nhanh càng tốt, loại bỏ tất ra khỏi đống chưa được sắp xếp cùng một lúc và đặt thành đống trước mặt bạn. Các cọc nên được sắp xếp một cách hiệu quả không gian, với tất cả các vớ cùng hướng; số lượng cọc được giới hạn bởi khoảng cách bạn có thể dễ dàng đạt được. Việc lựa chọn một cái cọc để đặt một chiếc tất phải là - càng nhanh càng tốt - bằng cách đặt một chiếc tất lên một đống có vẻ giống như vớ; loại I thỉnh thoảng (đặt một chiếc tất vào một cái cọc mà nó không thuộc về) hoặc loại II (đặt một chiếc tất vào trong đống của chính nó khi có một đống vớ giống như hiện tại) có thể được chấp nhận - điều quan trọng nhất là tốc độ .

Khi tất cả các vớ đã được chất thành đống, nhanh chóng đi qua các cọc nhiều vớ tạo ra các cặp và loại bỏ chúng (những thứ này đang hướng đến ngăn kéo). Nếu có vớ không phù hợp trong đống, hãy đóng cọc lại theo cách tốt nhất của chúng (trong giới hạn càng nhanh càng tốt). Khi tất cả các cọc nhiều vớ đã được xử lý, hãy ghép các vớ có thể đeo còn lại không được ghép nối do lỗi loại II. Whoosh, bạn đã hoàn tất - và tôi có rất nhiều vớ và không giặt chúng cho đến khi một phần lớn bị bẩn. Một lưu ý thực tế khác: Tôi lật mặt trên của một trong những đôi vớ khác, tận dụng các đặc tính đàn hồi của chúng, để chúng ở lại với nhau trong khi được vận chuyển đến ngăn kéo và trong khi ở trong ngăn kéo.


15

Từ câu hỏi của bạn, rõ ràng bạn không có nhiều kinh nghiệm thực tế với việc giặt giũ :). Bạn cần một thuật toán hoạt động tốt với một số lượng nhỏ vớ không thể mang.

Các câu trả lời cho đến bây giờ không sử dụng tốt các khả năng nhận dạng mẫu người của chúng tôi. Trò chơi Set cung cấp manh mối về cách thực hiện tốt điều này: đặt tất cả tất vào không gian hai chiều để bạn có thể nhận ra chúng tốt và dễ dàng tiếp cận chúng bằng tay. Điều này giới hạn bạn trong một khu vực khoảng 120 * 80 cm hoặc lâu hơn. Từ đó chọn các cặp bạn nhận ra và loại bỏ chúng. Đặt thêm vớ vào không gian trống và lặp lại. Nếu bạn giặt cho những người có vớ dễ nhận biết (trẻ nhỏ nghĩ đến), bạn có thể thực hiện sắp xếp cơ số bằng cách chọn những đôi tất đó trước. Thuật toán này chỉ hoạt động tốt khi số lượng vớ đơn thấp


Đó thường là cách tôi làm điều đó. Hoạt động tốt hơn nhiều so với việc lặp qua tất cả các vớ còn lại mỗi lần.
yu_ominae

Cách tiếp cận tốt đẹp và tôi nghĩ nó cũng có thể được áp dụng cho một số vấn đề CS thực sự. Bạn có thể vui lòng thêm một ví dụ về điều đó (một vấn đề CS trong đó chúng ta có thể sử dụng một cách tiếp cận tương tự để giải quyết vấn đề)? Ngoài ra, làm thế nào để giải pháp này quy mô cho hàng triệu vớ?
amit

Tôi nghĩ rằng điều này về cơ bản giống như câu trả lời khác ở đây, stackoverflow.com/a/14423956 , từ ngày 20 tháng 1. Cả +1. Hệ thống tầm nhìn của con người là song song lớn.
Will Ness

15

Nhặt một chiếc tất đầu tiên và đặt nó lên bàn. Bây giờ chọn một chiếc tất khác; nếu nó phù hợp với cái đầu tiên được chọn, đặt nó lên trên cái đầu tiên. Nếu không, đặt nó trên bàn một khoảng cách nhỏ từ đầu tiên. Chọn một chiếc tất thứ ba; nếu nó khớp với một trong hai cái trước, đặt nó lên trên chúng hoặc đặt nó cách một khoảng nhỏ so với cái thứ ba. Lặp lại cho đến khi bạn đã chọn tất cả các vớ.


1
Đây là câu trả lời hợp lệ duy nhất. Tất cả những người khác đều không quan tâm đến thực tế rằng phần lớn thời gian được dành để phân biệt giữa những đôi tất tương tự (do đó, việc kết hợp chúng lại với nhau bằng ngoại hình thực tế khiến nó thậm chí còn tồi tệ hơn).
entonio

Để giải trí, tôi đã viết phương pháp chồng tất này lên một chương trình python nhỏ gist.github.com/justinfay/53b574cf0a492f6795ef
Justin Fay

12

Để nói được hiệu quả của việc ghép tất từ ​​một đống, chúng ta phải xác định máy trước, bởi vì việc ghép đôi không được thực hiện dù là bằng cách sử dụng hay sử dụng máy truy cập ngẫu nhiên, thường được sử dụng làm cơ sở cho một phân tích thuật toán.

Máy

Cỗ máy là sự trừu tượng của một yếu tố trong thế giới thực gọi là con người. Nó có thể đọc từ môi trường thông qua một đôi mắt. Và mô hình máy của chúng tôi có thể thao túng môi trường bằng cách sử dụng 2 cánh tay. Các hoạt động logic và số học được tính toán bằng bộ não của chúng tôi (hy vọng ;-)).

Chúng ta cũng phải xem xét thời gian chạy nội tại của các hoạt động nguyên tử có thể được thực hiện với các công cụ này. Do các ràng buộc vật lý, các hoạt động được thực hiện bởi một cánh tay hoặc mắt có độ phức tạp thời gian không đổi. Điều này là do chúng ta không thể di chuyển một đống vớ lớn vô tận bằng một cánh tay cũng như mắt không thể nhìn thấy chiếc tất trên cùng trên một đống vớ lớn vô tận.

Tuy nhiên vật lý cơ học cũng cho chúng ta một số goodies. Chúng tôi không giới hạn di chuyển nhiều nhất một chiếc tất bằng một cánh tay. Chúng ta có thể di chuyển cả một vài trong số chúng cùng một lúc.

Vì vậy, tùy thuộc vào phân tích trước, các thao tác sau nên được sử dụng theo thứ tự giảm dần:

  • hoạt động logic và số học
  • đọc môi trường
  • sửa đổi môi trường

Chúng ta cũng có thể sử dụng thực tế là mọi người chỉ có một số lượng vớ rất hạn chế. Vì vậy, một sửa đổi môi trường có thể liên quan đến tất cả các vớ trong đống.

Thuật toán

Vì vậy, đây là gợi ý của tôi:

  1. Trải tất tất trong đống trên sàn nhà.
  2. Tìm một đôi bằng cách nhìn vào những chiếc vớ trên sàn nhà.
  3. Lặp lại từ 2 cho đến khi không có cặp nào có thể được thực hiện.
  4. Lặp lại từ 1 cho đến khi không có vớ trên sàn.

Hoạt động 4 là cần thiết, bởi vì khi trải tất trên sàn nhà, một số vớ có thể che giấu những người khác. Dưới đây là phân tích của thuật toán:

Phân tích

Thuật toán chấm dứt với xác suất cao. Điều này là do thực tế là người ta không thể tìm thấy đôi vớ ở bước số 2.

Đối với phân tích thời gian chạy sau đây về các ncặp vớ, chúng tôi giả sử rằng ít nhất một nửa số 2nvớ không bị ẩn sau bước 1. Vì vậy, trong trường hợp trung bình chúng ta có thể tìm thấy n/2các đôi. Điều này có nghĩa là vòng lặp là bước 4 được thực hiện O(log n)lần. Bước 2 được thực hiện O(n^2)lần. Vì vậy, chúng tôi có thể kết luận:

  • Thuật toán bao gồm O(ln n + n)sửa đổi môi trường (bước 1 O(ln n)cộng với chọn từng cặp vớ từ sàn)
  • Thuật toán bao gồm O(n^2)các lần đọc môi trường từ bước 2
  • Thuật toán bao gồm O(n^2)các phép toán logic và số học để so sánh một chiếc tất với cái khác trong bước 2

Vì vậy, chúng tôi có tổng độ phức tạp thời gian chạy ở O(r*n^2 + w*(ln n + n))đâu rwlà các yếu tố cho các hoạt động đọc và ghi môi trường tương ứng cho một số lượng vớ hợp lý. Chi phí của các phép toán logic và số học được bỏ qua, bởi vì chúng tôi cho rằng phải mất một số lượng không đổi các phép toán logic và số học để quyết định xem 2 vớ có thuộc cùng một cặp hay không. Điều này có thể không khả thi trong mọi kịch bản.


1
điều này giống như stackoverflow.com/a/14423956stackoverflow.com/a/14468913 tôi nghĩ vậy.
Will Ness

@WillNess Yep, với một chút giải thích
SpaceTrucker

12
List<Sock> UnSearchedSocks = getAllSocks();
List<Sock> UnMatchedSocks = new list<Sock>();
List<PairOfSocks> PairedSocks = new list<PairOfSocks>();

foreach (Sock newSock in UnsearchedSocks)
{
  Sock MatchedSock = null;
  foreach(Sock UnmatchedSock in UnmatchedSocks)
  {
    if (UnmatchedSock.isPairOf(newSock))
    {
      MatchedSock = UnmatchedSock;
      break;
    }
  }
  if (MatchedSock != null)
  {
    UnmatchedSocks.remove(MatchedSock);
    PairedSocks.Add(new PairOfSocks(MatchedSock, NewSock));
  }
  else
  {
    UnmatchedSocks.Add(NewSock);
  }
}

12

Tôi đã đưa ra một giải pháp khác sẽ không hứa hẹn ít hoạt động hơn, không tốn thời gian hơn, nhưng nên thử xem liệu nó có thể là một heuristic đủ tốt để cung cấp ít thời gian hơn trong chuỗi ghép sock lớn.

Điều kiện tiên quyết: Không có gì đảm bảo rằng có những đôi tất giống nhau. Nếu chúng có cùng màu thì không có nghĩa là chúng có cùng kích thước hoặc hoa văn. Vớ được xáo trộn ngẫu nhiên. Có thể có số lượng vớ lẻ (một số bị thiếu, chúng tôi không biết có bao nhiêu). Chuẩn bị ghi nhớ một "chỉ mục" biến và đặt nó thành 0.

Kết quả sẽ có một hoặc hai cọc: 1. "khớp" và 2. "thiếu"

Heuristic:

  1. Tìm sock đặc biệt nhất.
  2. Tìm trận đấu của nó.
  3. Nếu không có kết quả khớp, đặt nó vào đống "mất tích".
  4. Lặp lại từ 1. cho đến khi không có vớ đặc biệt hơn.
  5. Nếu có ít hơn 6 vớ, hãy đến 11.
  6. Ghép đôi tất tất với hàng xóm của nó (không đóng gói)
  7. Tìm tất cả các cặp khớp, đóng gói và di chuyển các cặp đã đóng gói thành cọc "khớp"; Nếu không có trận đấu mới - "chỉ số" tăng thêm 1
  8. Nếu "chỉ số" lớn hơn 2 (điều này có thể là giá trị phụ thuộc vào số sock vì với số lượng vớ nhiều hơn sẽ có ít cơ hội để ghép chúng một cách mù quáng) đi đến 11
  9. Xáo trộn phần còn lại
  10. Chuyển đến 1
  11. Quên "chỉ số"
  12. Chọn một chiếc tất
  13. Tìm cặp của nó
  14. Nếu không có cặp cho tất, hãy di chuyển nó đến đống "mất tích"
  15. Nếu tìm thấy kết hợp ghép nó, đóng gói cặp và di chuyển nó đến đống "khớp"
  16. Nếu vẫn còn nhiều thì một vớ đi đến 12
  17. Nếu chỉ còn một trái, hãy đến 14
  18. Nụ cười hài lòng :)

Ngoài ra, có thể có thêm kiểm tra cho những đôi tất bị hư hỏng, như thể loại bỏ những đôi đó. Nó có thể được chèn vào giữa 2 và 3, và từ 13 đến 14.

Tôi mong muốn được nghe về bất kỳ kinh nghiệm hoặc sửa chữa.


Sau khi tôi viết nó, tôi sử dụng nó mỗi lần. Nó giúp tôi trở nên hiệu quả hơn một chút và công việc bây giờ đã bớt nhàm chán.
Sasa

11

Khi tôi sắp xếp tất, tôi thực hiện một loại cơ số gần đúng , thả tất gần các loại vớ khác có cùng màu / kiểu mẫu. Ngoại trừ trong trường hợp khi tôi có thể thấy một trận đấu chính xác tại / gần vị trí tôi sắp bỏ chiếc tất tôi rút ra cặp đó vào thời điểm đó.

Hầu như tất cả các thuật toán khác (bao gồm câu trả lời hàng đầu của usr ), sau đó loại bỏ các cặp. Tôi thấy rằng, là một con người, tốt hơn là giảm thiểu số lượng vớ được xem xét cùng một lúc.

Tôi làm điều này bằng cách:

  1. Chọn một chiếc tất đặc biệt (bất cứ thứ gì bắt mắt tôi đầu tiên trong đống).
  2. Bắt đầu một loại cơ số từ vị trí khái niệm đó bằng cách kéo tất từ ​​đống dựa trên sự tương tự với vị trí đó.
  3. Đặt chiếc tất mới vào gần đống hiện tại, với khoảng cách dựa trên mức độ khác nhau của nó. Nếu bạn thấy mình đặt chiếc tất lên trên cái khác vì nó giống hệt nhau, hãy tạo thành cặp ở đó và loại bỏ chúng. Điều này có nghĩa là các so sánh trong tương lai mất ít nỗ lực hơn để tìm đúng nơi.

Điều này tận dụng khả năng của con người để so khớp mờ trong thời gian O (1), tương đương với việc thiết lập bản đồ băm trên thiết bị điện toán.

Bằng cách kéo vớ đặc biệt trước, bạn sẽ chừa không gian để "phóng to" các tính năng ít đặc biệt hơn để bắt đầu.

Sau khi loại bỏ màu fluro, vớ có sọc và ba đôi vớ dài, bạn có thể kết thúc với hầu hết các loại vớ trắng được sắp xếp một cách thô sơ theo mức độ chúng bị mòn.

Tại một số điểm, sự khác biệt giữa các vớ đủ nhỏ để người khác không nhận thấy sự khác biệt và không cần bất kỳ nỗ lực phù hợp nào nữa.


10

Bất cứ khi nào bạn nhặt một chiếc tất, hãy đặt nó ở một nơi. Sau đó, chiếc tất tiếp theo bạn nhặt, nếu nó không khớp với chiếc tất đầu tiên, hãy đặt nó bên cạnh chiếc tất đầu tiên. Nếu có, có một cặp. Bằng cách này, nó thực sự không quan trọng có bao nhiêu kết hợp, và chỉ có hai khả năng cho mỗi chiếc vớ bạn nhặt - hoặc nó có một trận đấu đã có trong mảng vớ của bạn, hoặc nó không có nghĩa là bạn thêm nó vào một vị trí trong mảng

Điều này cũng có nghĩa là bạn gần như chắc chắn sẽ không bao giờ có tất cả trong tất cả, vì tất sẽ bị loại bỏ khi chúng khớp.


Đây là những gì tôi làm ... O (n)
Pykler

2
@Pykler - Đó là O (n) trong trường hợp tốt nhất và O (n * n) trong trường hợp xấu nhất.
Vilx-

2
Điều đó giả định rằng bạn không thể tạo ra một hàm băm hoàn toàn độc đáo trong tâm trí của bạn về tất cả những đôi tất bạn đã thấy, mà đối với tôi là một chữ O (1) để khớp với một chiếc tất mà tôi đã thấy và trước đó và đặt trong đó để chờ băm
Pykler

10

Hãy xem xét một bảng băm có kích thước 'N'.

Nếu chúng tôi giả định phân phối bình thường, thì số lượng 'chèn' ước tính để có ít nhất một sock được ánh xạ tới một nhóm là NlogN (nghĩa là tất cả các thùng đều đầy)

Tôi đã nhận ra đây là một phần của câu đố khác, nhưng tôi sẽ rất vui khi được chứng minh là sai. Đây là bài viết trên blog của tôi trên cùng

Đặt 'N' tương ứng với giới hạn trên gần đúng về số lượng màu sắc / mẫu vớ độc đáo mà bạn có.

Một khi bạn có một vụ va chạm (hay còn gọi là trận đấu) chỉ cần tháo đôi vớ đó ra. Lặp lại thí nghiệm tương tự với lô vớ NlogN tiếp theo. Cái hay của nó là bạn có thể tạo ra các so sánh song song (giải quyết va chạm) của NlogN vì cách thức hoạt động của tâm trí con người. :-)


10

Vớ, cho dù là người thật hay cấu trúc dữ liệu tương tự, sẽ được cung cấp theo cặp.

Câu trả lời đơn giản nhất là trước khi cho phép tách cặp, một cấu trúc dữ liệu duy nhất cho cặp nên được khởi tạo có chứa một con trỏ ở bên trái và bên phải, do đó cho phép vớ được chuyển trực tiếp hoặc qua cặp của chúng. Một chiếc tất cũng có thể được mở rộng để chứa một con trỏ tới đối tác của nó.

Điều này giải quyết bất kỳ vấn đề ghép cặp tính toán nào bằng cách loại bỏ nó bằng một lớp trừu tượng.

Áp dụng cùng một ý tưởng cho vấn đề thực tế của việc ghép tất, câu trả lời rõ ràng là: không cho phép đôi tất của bạn không bị ghép đôi. Vớ được cung cấp như một đôi, đặt trong ngăn kéo như một cặp (có lẽ bằng cách ghép chúng lại với nhau), mặc như một đôi. Nhưng điểm không thể ghép đôi là trong máy giặt, vì vậy tất cả những gì cần thiết là một cơ chế vật lý cho phép tất ở lại với nhau và được giặt hiệu quả.

Có hai khả năng vật lý:

Đối với một đối tượng 'cặp' giữ một con trỏ cho mỗi chiếc tất, chúng ta có thể có một túi vải mà chúng ta sử dụng để giữ tất cùng nhau. Điều này có vẻ như trên đầu lớn.

Nhưng đối với mỗi chiếc tất để giữ một tham chiếu đến cái khác, có một giải pháp gọn gàng: một popper (hoặc 'nút snap' nếu bạn là người Mỹ), chẳng hạn như:

http://www.al.co.com/compare/compare-invisible-snap-buttons.html

Sau đó, tất cả những gì bạn làm là gắn tất của bạn lại với nhau ngay sau khi bạn tháo chúng ra và bỏ chúng vào giỏ giặt của bạn, và một lần nữa bạn đã loại bỏ vấn đề cần phải đi tất với khái niệm trừu tượng về 'cặp'.


Nó không trả lời câu hỏi, vì việc xử lý với dữ liệu đã được ghép nối rất dễ dàng, câu hỏi là phải làm gì khi dữ liệu KHÔNG BỊ XÓA và bạn muốn ghép nó.
amit

8

Nếu thao tác "di chuyển" khá tốn kém và thao tác "so sánh" rẻ và bạn vẫn cần di chuyển toàn bộ tập hợp, vào bộ đệm nơi tìm kiếm nhanh hơn nhiều so với lưu trữ ban đầu ... chỉ cần tích hợp sắp xếp vào bắt buộc di chuyển.

Tôi thấy việc tích hợp quá trình phân loại thành treo để làm cho nó dễ dàng. Dù sao tôi cũng cần nhặt từng chiếc tất và treo nó (di chuyển) và tôi sẽ không mất gì khi treo nó ở một vị trí cụ thể trên dây. Bây giờ chỉ cần không bắt buộc tìm kiếm toàn bộ bộ đệm (dây) tôi chọn đặt vớ theo màu / bóng. Bên trái tối hơn, bên phải sáng hơn, phía trước nhiều màu sắc hơn, v.v ... Bây giờ trước khi tôi treo từng chiếc tất, tôi nhìn vào "vùng bên phải" của nó nếu đã có một cái phù hợp - điều này giới hạn "quét" đến 2-3 chiếc vớ khác - và nếu nó là , Tôi treo cái khác ngay bên cạnh. Sau đó, tôi cuộn chúng thành cặp trong khi gỡ khỏi dây, khi khô.

Bây giờ điều này có vẻ không khác lắm so với "tạo cọc theo màu" được đề xuất bởi các câu trả lời hàng đầu nhưng trước tiên, bằng cách không chọn các cọc rời rạc nhưng phạm vi, tôi không có vấn đề gì trong việc phân loại xem "màu tím" chuyển sang cọc "đỏ" hay "xanh"; nó chỉ đi giữa Và sau đó bằng cách tích hợp hai thao tác (treo để sấy và sắp xếp) chi phí phân loại trong khi treo giống như 10% của phân loại riêng biệt.


Cách tiếp cận này có hai ưu điểm khác: sấy khô dây chuyền mất ít vớ IME hơn so với máy sấy quần áo, và quy trình phân loại có thể được mở rộng sang phần còn lại của đồ giặt, vì vậy (ví dụ) tất cả các khăn nằm gần nhau để được gấp lại dòng và binned và đưa thẳng đến lưu trữ của họ. Nó cũng hoạt động trong hai lần vượt qua nỗ lực thấp, đưa quần áo lên và đưa chúng xuống một lần nữa.
cphlewis

8

Tôi đã hoàn thành việc ghép đôi tất của mình ngay bây giờ và tôi thấy rằng cách tốt nhất để làm điều đó là như sau:

  • Chọn một trong những chiếc vớ và cất nó đi (tạo một 'cái xô' cho đôi đó)
  • Nếu cái tiếp theo là cặp của cái trước, sau đó đặt nó vào thùng hiện có, nếu không thì tạo cái mới.

Trong trường hợp xấu nhất, điều đó có nghĩa là bạn sẽ có n / 2 nhóm khác nhau và bạn sẽ có n-2 xác định về loại xô nào chứa cặp vớ hiện tại. Rõ ràng, thuật toán này hoạt động tốt nếu bạn chỉ có một vài cặp; Tôi đã làm điều đó với 12 cặp.

Nó không quá khoa học, nhưng nó hoạt động tốt :)


Đây vẫn là thuật toán O (n ^ 2) vì bạn phải lặp lại trên mỗi nhóm bất cứ khi nào bạn rút ra một chiếc tất mới. Nhưng, xem xét thực tế là ngay cả những đôi tất được mua trong cùng một lô cũng có những khác biệt nhỏ khiến chúng trở nên độc nhất vô nhị (hoặc thậm chí là duy nhất), dù sao đi nữa
Semisonic

Đồng ý, nhưng thuật toán của tôi cho rằng con người đang thực hiện ghép nối. Do đó, sẽ có một loại bộ nhớ cache trong tâm trí của bạn khi bạn đang tìm kiếm nhóm phù hợp, vì vậy dù sao bạn cũng không thực sự cần phải lặp lại các nhóm. Không chắc chắn loại cấu trúc dữ liệu nào được xây dựng cho cơ chế bộ đệm này trong đầu tôi trong quá trình ghép nối.
maestro

8

Giải pháp của tôi không chính xác tương ứng với yêu cầu của bạn, vì nó chính thức yêu cầu O(n)không gian "thêm". Tuy nhiên, xem xét các điều kiện của tôi, nó rất hiệu quả trong ứng dụng thực tế của tôi. Vì vậy, tôi nghĩ rằng nó nên thú vị.

Kết hợp với nhiệm vụ khác

Điều kiện đặc biệt trong trường hợp của tôi là tôi không sử dụng máy sấy, chỉ treo quần áo trên máy sấy vải thông thường. Treo vải đòi hỏi các O(n)hoạt động (nhân tiện, tôi luôn xem xét vấn đề đóng gói bin ở đây) và vấn đề theo bản chất của nó đòi hỏi không gian "phụ" tuyến tính. Khi tôi lấy một chiếc tất mới từ thùng, tôi sẽ thử treo nó bên cạnh cặp của nó nếu cặp đã được treo. Nếu đó là một chiếc tất từ ​​một cặp mới, tôi sẽ chừa một khoảng trống bên cạnh nó.

Máy Oracle tốt hơn ;-)

Nó rõ ràng đòi hỏi một số công việc bổ sung để kiểm tra xem có một chiếc tất phù hợp đã được treo ở đâu đó không và nó sẽ đưa ra giải pháp O(n^2)với hệ số về 1/2cho một máy tính. Nhưng trong trường hợp này, "yếu tố con người" thực sự là một lợi thế - tôi thường có thể nhanh chóng (gần như O(1)) xác định được chiếc tất phù hợp nếu nó đã được treo (có thể có một số bộ nhớ đệm trong não không thể chấp nhận được) - coi đó là một loại "tiên tri" hạn chế như trong Máy Oracle ;-) Chúng tôi, con người có những lợi thế này so với máy kỹ thuật số trong một số trường hợp ;-)

Có nó gần như O(n)!

Do đó, kết nối vấn đề ghép vớ với vấn đề treo vải tôi nhận được O(n)"không gian thêm" miễn phí và có một giải pháp O(n)kịp thời, chỉ cần một công việc nhỏ hơn vải treo đơn giản và cho phép truy cập ngay vào cặp hoàn chỉnh tất ngay cả trong một buổi sáng thứ Hai rất tệ ... ;-)


8

Tôi hy vọng tôi có thể đóng góp một cái gì đó mới cho vấn đề này. Tôi nhận thấy rằng tất cả các câu trả lời đều bỏ qua thực tế là có hai điểm bạn có thể thực hiện tiền xử lý mà không làm chậm hiệu suất giặt chung của bạn.

Ngoài ra, chúng ta không cần phải sử dụng một số lượng lớn tất, ngay cả đối với các gia đình lớn. Vớ được lấy ra khỏi ngăn kéo và được mặc, và sau đó chúng được ném vào một nơi (có thể là thùng) nơi chúng ở trước khi được giặt. Mặc dù tôi sẽ không gọi bin là LIFO-Stack, tôi nói rằng sẽ an toàn khi cho rằng

  1. mọi người ném cả hai chiếc vớ của họ vào cùng một khu vực của thùng,
  2. thùng không được ngẫu nhiên tại bất kỳ điểm nào, và do đó
  3. bất kỳ tập hợp con nào được lấy từ đỉnh của thùng này thường chứa cả hai đôi tất.

Vì tất cả các máy giặt mà tôi biết đều bị giới hạn về kích thước (bất kể bạn phải giặt bao nhiêu vớ) và ngẫu nhiên thực sự xảy ra trong máy giặt, cho dù chúng tôi có bao nhiêu vớ, chúng tôi luôn có các tập con nhỏ gần như không có người độc thân.

Hai giai đoạn tiền xử lý của chúng tôi là "đặt tất vào dây phơi" và "Lấy tất từ ​​dây phơi", điều chúng tôi phải làm, để có được những đôi tất không chỉ sạch mà còn khô. Như với máy giặt, dây phơi là hữu hạn, và tôi cho rằng chúng ta có toàn bộ dây chuyền nơi chúng ta đặt tất vào tầm nhìn.

Đây là thuật toán cho put_socks_on_line ():

while (socks left in basket) {
 take_sock();
 if (cluster of similar socks is present) { 
   Add sock to cluster (if possible, next to the matching pair)
 } else {
  Hang it somewhere on the line, this is now a new cluster of similar-looking socks.      
  Leave enough space around this sock to add other socks later on 
 }
}

Đừng lãng phí thời gian của bạn để di chuyển tất xung quanh hoặc tìm kiếm một trận đấu tốt nhất, tất cả điều này nên được thực hiện trong O (n), điều mà chúng ta cũng sẽ cần cho việc đưa chúng vào dòng chưa được sắp xếp. Những đôi tất chưa được ghép nối, chúng tôi chỉ có một số cụm tương tự trên dòng. Thật hữu ích khi chúng tôi có một bộ vớ hạn chế ở đây, vì điều này giúp chúng tôi tạo ra các cụm "tốt" (ví dụ: nếu chỉ có vớ đen trong bộ vớ, việc phân cụm theo màu sẽ không phải là cách để đi)

Đây là thuật toán cho Take_socks_from_line ():

while(socks left on line) {
 take_next_sock();
 if (matching pair visible on line or in basket) {
   Take it as well, pair 'em and put 'em away
 } else {
   put the sock in the basket
 }

Tôi nên chỉ ra rằng để cải thiện tốc độ của các bước còn lại, không nên chọn ngẫu nhiên sock tiếp theo, mà phải tuần tự đi tất sau khi sock từ mỗi cụm. Cả hai bước tiền xử lý không mất nhiều thời gian hơn là chỉ đặt tất lên dây chuyền hoặc trong giỏ, điều mà chúng ta phải làm bất kể là gì, vì vậy điều này sẽ giúp tăng cường đáng kể hiệu suất giặt.

Sau này, thật dễ dàng để thực hiện thuật toán phân vùng băm. Thông thường, khoảng 75% số vớ đã được ghép nối, để lại cho tôi một tập hợp vớ rất nhỏ và tập hợp con này đã được phân cụm (phần nào) (tôi không đưa nhiều entropy vào giỏ của mình sau các bước tiền xử lý). Một điều nữa là các cụm còn lại có xu hướng đủ nhỏ để được xử lý cùng một lúc, vì vậy có thể lấy toàn bộ cụm ra khỏi giỏ.

Đây là thuật toán cho sort_remained_cl cluster ():

while(clusters present in basket) {
  Take out the cluster and spread it
  Process it immediately
  Leave remaining socks where they are
}

Sau đó, chỉ còn một vài chiếc vớ. Đây là nơi tôi giới thiệu những đôi vớ chưa từng có trước đây vào hệ thống và xử lý những chiếc vớ còn lại mà không có bất kỳ thuật toán đặc biệt nào - những chiếc vớ còn lại rất ít và có thể được xử lý trực quan rất nhanh.

Đối với tất cả các vớ còn lại, tôi cho rằng các đối tác của họ vẫn chưa được rửa sạch và đặt chúng đi cho lần lặp tiếp theo. Nếu bạn đăng ký tăng trưởng vớ không theo thời gian ("rò rỉ tất"), bạn nên kiểm tra thùng của mình - nó có thể được chọn ngẫu nhiên (bạn có mèo ngủ ở đó không?)

Tôi biết rằng các thuật toán này có rất nhiều giả định: một thùng hoạt động như một loại LIFO, máy giặt bình thường, hạn chế và dây phơi quần áo bình thường, hạn chế - nhưng nó vẫn hoạt động với số lượng vớ rất lớn.

Về song song: Miễn là bạn ném cả hai chiếc tất vào cùng một thùng, bạn có thể dễ dàng song song tất cả các bước đó.


Vớ chỉ là phép ẩn dụ để ghép các đối tượng tùy ý trong một số cơ sở dữ liệu.
amit

1
Có nó, không thấy rằng bạn là tác giả. Nếu bạn muốn một giải pháp chung chung, bạn thực sự nên nói như vậy. Dù sao, không có gì sai khi lấy bất kỳ thông tin nào bạn có, trừ khi bạn phải đưa ra giải pháp chung - từ bỏ khả năng sử dụng lại giải pháp có thể mang lại hiệu quả tốt hơn đáng kể. Trong trường hợp này, xem xét trường hợp sử dụng và cơ sở dữ liệu có sẵn nói chung là có lợi. Tuy nhiên, câu trả lời đặc biệt này cho câu hỏi đặc biệt của bạn có vấn đề với những đôi tất có hình dáng tương tự, ví dụ như vớ đen ở các kích cỡ khác nhau, vì vậy nó không được áp dụng trong một số trường hợp.
Philipp Flenker

1
Ngoài ra, bạn không nhận được> 2k upvote vì bạn đã hỏi một câu hỏi về việc ghép các đối tượng tùy ý trong cơ sở dữ liệu. Bạn đặc biệt hạn chế câu hỏi do bản chất của vớ (mà bạn không thể sao chép, trái ngược với dữ liệu), bạn thậm chí còn khuyến khích sử dụng thực tế là bạn có thể dễ dàng phân biệt vớ của bạn với vớ của bạn đời. Nếu bạn đặt câu hỏi về vớ, đừng mong đợi câu trả lời là về cơ sở dữ liệu ;-)
Philipp Flenker

1
Có một vài giả định: mashine giặt bình thường, a, dây phơi quần áo bình thường và thực tế là bạn ném cả hai chiếc tất vào thùng cùng một lúc, điều đó có nghĩa là trong hầu hết các trường hợp, cả hai chiếc vớ đều nằm trong cùng một máy và số lượng Do đó, tất còn lại để được sắp xếp là nhỏ. Nhưng vì bạn thực sự muốn có một câu trả lời về việc lưu trữ các đối tượng tùy ý trong cơ sở dữ liệu, nó có thực sự hữu ích khi thảo luận về giải pháp của tôi không?
Philipp Flenker

1
Như tôi đã nói, tôi nghĩ rằng tôi đã giải quyết tất cả mọi thứ bạn yêu cầu, ngoại trừ vấn đề khác biệt về yếu tố, đã được người khác trả lời. Tôi không cố gắng để trở thành một người thụt rửa ở đây, nhưng tôi đã nỗ lực rất nhiều trong câu trả lời này một thời gian và tôi hơi thất vọng vì bây giờ bạn đã trải qua một số câu trả lời và cho rằng họ không trả lời câu hỏi ban đầu . Tại sao bạn không để lại toàn bộ chủ đề một mình - nó vẫn là một bài đọc thú vị, hơn 2 năm sau khi bạn hỏi nó?
Philipp Flenker

8

Tôi đã thực hiện các bước đơn giản để giảm nỗ lực của mình vào quá trình mất thời gian O (1).

Bằng cách giảm đầu vào của tôi xuống một trong hai loại vớ (vớ trắng để giải trí, vớ đen cho công việc), tôi chỉ cần xác định loại vớ nào tôi có trong tay. (Về mặt kỹ thuật, vì chúng không bao giờ được rửa cùng nhau, tôi đã giảm quá trình xuống còn O (0).)

Một số nỗ lực trả trước là cần thiết để tìm ra những đôi tất mong muốn và mua với số lượng đủ để loại bỏ nhu cầu cho những đôi tất hiện có của bạn. Như tôi đã làm điều này trước khi tôi cần vớ đen, nỗ lực của tôi là tối thiểu, nhưng số dặm có thể thay đổi.

Một nỗ lực trả trước như vậy đã được nhìn thấy nhiều lần trong mã rất phổ biến và hiệu quả. Các ví dụ bao gồm # DEFINE'ing pi cho một số số thập phân (ví dụ khác tồn tại, nhưng đó là một trong những điều mà tôi nghĩ đến ngay bây giờ).


7

Tạo một bảng băm sẽ được sử dụng cho những đôi tất chưa từng có, sử dụng mẫu làm băm. Lặp đi lặp lại trên tất từng cái một. Nếu chiếc tất có khớp mẫu trong bảng băm, hãy lấy chiếc tất ra khỏi bàn và tạo một cặp. Nếu chiếc tất không có khớp, hãy đặt nó vào bàn.


Làm thế nào để làm điều đó không tại chỗ, như được đề cập cụ thể trong câu hỏi?
amit

7

Vấn đề sắp xếp n đôi vớ của bạn là O (n) . Trước khi bạn ném chúng vào giỏ giặt , bạn luồn cái bên trái sang cái bên phải. Khi lấy chúng ra, bạn cắt chỉ và đặt từng cặp vào ngăn kéo của bạn - 2 thao tác trên n cặp, vì vậy O (n).

Bây giờ câu hỏi tiếp theo chỉ đơn giản là liệu bạn có tự giặt đồ không và vợ bạn có làm của cô ấy không. Đó là một vấn đề có thể xảy ra trong một lĩnh vực hoàn toàn khác . :)


Điều này không trả lời câu hỏi, trong đó tất chỉ là một phép ẩn dụ.
amit

Câu hỏi là làm thế nào để ghép đôi vớ từ một đống không ghép đôi, không phải làm thế nào để tránh cần phải ghép.
amit
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.