ค้นหาว่าใครจะซื้อครัวซองต์ซึ่งคิดว่าหายไป


13

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

ข้อ จำกัด สมมติฐานและวัตถุประสงค์:

  • ที่เปิดก็จะนำครัวซองต์จะถูกกำหนดในช่วงบ่ายก่อนหน้า
  • ในบางวันบางคนไม่อยู่ อัลกอริทึมต้องเลือกใครบางคนที่จะนำเสนอในวันนั้น สมมติว่าการขาดทั้งหมดเป็นที่ทราบล่วงหน้าหนึ่งวันดังนั้นผู้ซื้อครัวซองต์สามารถถูกกำหนดในช่วงบ่ายก่อนหน้า
  • โดยรวมแล้วคนส่วนใหญ่อยู่ในเกือบทุกวัน
  • เพื่อผลประโยชน์ของความเป็นธรรมทุกคนควรซื้อครัวซองต์หลายครั้ง (โดยทั่วไปสมมติว่าสมาชิกทุกคนในทีมมีจำนวนเงินเท่ากันสำหรับการใช้จ่ายกับครัวซองต์)
  • มันจะดีถ้ามีองค์ประกอบของการสุ่มหรือการรับรู้อย่างน้อยที่สุดเพื่อที่จะบรรเทาความเบื่อของบัญชีรายชื่อ นี่ไม่ใช่ข้อ จำกัด อย่างหนัก: มันเป็นการตัดสินใจเชิงสุนทรียะมากกว่า อย่างไรก็ตามบุคคลเดียวกันไม่ควรเลือกสองครั้งติดต่อกัน
  • บุคคลที่นำครัวซองต์มาด้วยควรทราบล่วงหน้า ดังนั้นหากบุคคล P ต้องนำครัวซองต์ในวันที่ D ดังนั้นความจริงข้อนี้ควรถูกกำหนดในวันก่อนหน้าซึ่งมีบุคคล P อยู่ด้วย ตัวอย่างเช่นหากพนักงานเก็บเงินตัวสำรองถูกกำหนดวันก่อนเสมอควรเป็นหนึ่งในบุคคลที่เข้าร่วมเมื่อวานนี้
  • จำนวนสมาชิกในทีมมีขนาดเล็กเพียงพอที่ทรัพยากรการจัดเก็บและการคำนวณมีไม่ จำกัด อย่างมีประสิทธิภาพ ตัวอย่างเช่นอัลกอริทึมสามารถพึ่งพาประวัติที่สมบูรณ์ของผู้ที่นำครัวซองต์เมื่อในอดีต การคำนวณบนพีซีที่รวดเร็วเพียงไม่กี่นาทีทุกวันก็โอเค

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


จุดกำเนิด 1: ค้นหาว่าใครกำลังจะซื้อครัวซองต์โดย Florian Margaine
จุดกำเนิด 2: ค้นหาว่าใครกำลังจะซื้อครัวซองต์โดยกิลส์
คำถามนี้เป็นรุ่นเดียวกับ Gilles และได้รับการโพสต์ใหม่ในโปรแกรมเมอร์เพื่อทดสอบว่าชุมชนต่าง ๆ จัดการกับปัญหาการเขียนโปรแกรมอย่างไร


2
เพิ่มประกาศโพสต์ฉันจะป้องกันหากจำเป็น แต่ฉันต้องการเปิดไว้ให้นานที่สุดเท่าที่จะทำได้ เกี่ยวกับคำถามนี้ในทางใดทางหนึ่งมันเป็นการทดลอง มันจะยังคงเปิดอยู่ วิทยาศาสตร์!
วิศวกรโลก

4
เหมาะสำหรับ Code Golf หรือไม่
ozz

3
ใครสน? ไม่มีทีมที่เคารพตนเองจะมีครัวซองต์ ตอนนี้โดนัทก็เป็นคำถามที่น่าสนใจ
Ross Patterson

3
ฟังดูเหมือนเป็นกรณีการใช้งานที่สมบูรณ์แบบสำหรับ DA Form 6 (ห่ามันใช้งานได้กับกองทัพมาตั้งแต่ปี 1974!) ดู AR 220-45 สำหรับการใช้งาน มันควรจะง่ายในการแปลว่าเป็นอัลกอริทึม
Adam Balsam

2
(หากต้องการขยาย @AdamBalsam แบบฟอร์มarmypubs.army.mil/eforms/pdf/A6.PDFและการใช้งานapd.army.mil/pdffiles/r220_45.pdf ... และโปรดอย่าแนะนำสิ่งนี้กับอดีตนายจ้างของฉัน มีนโยบายและขั้นตอนเพียงพอตามที่มันเป็น)

คำตอบ:


26

ฉันจะใช้อัลกอริทึมการให้คะแนน แต่ละคนเริ่มต้นด้วยคะแนนศูนย์ ทุกครั้งที่พวกเขานำครัวซองต์เพิ่มคะแนนโดย 1 คะแนนของสมาชิกในทีมทั้งหมดที่ไม่ได้นำครัวซองต์จะลดลง 1 / N ดังนั้นคะแนน 0 หมายความว่าสมาชิกในทีมไม่มียอดซื้อสูงหรือต่ำ

โดยไม่มีการสุ่มเลือกคนที่มีคะแนนต่ำสุดออกมาจากรายชื่อผู้ที่จะนำเสนอ

ในการเพิ่มการสุ่มให้เรียงลำดับรายการตามคะแนนและเลือกสุ่มจากรายชื่อสมาชิกทีมทั้งหมดด้วยคะแนนติดลบ ด้วยการ จำกัด คะแนนติดลบคุณจะมั่นใจได้ว่าจะไม่มีใคร "โชคดี" ในช่วงหลายสัปดาห์ที่ผ่านมา

ข้อได้เปรียบของอัลกอริธึมนี้คือมันไม่มีความเชื่อมั่นในการเก็บบันทึกทางประวัติศาสตร์และช่วยให้สามารถเพิ่มสมาชิกทีมใหม่ได้ทุกเวลา

มันสามารถปรับให้อนุญาตสำหรับการขาดหายไปเป็นเรื่องธรรมดาโดยการลดคะแนนของเฉพาะในปัจจุบันที่จะเพลิดเพลินกับครัวซองต์


3
ฉันคิดว่าย่อหน้าสุดท้ายของคุณมีความสำคัญมิฉะนั้นคนที่ไปเที่ยวพักผ่อนเป็นเวลาหนึ่งเดือน (อาจจะดื่มน้ำผึ้งพระจันทร์) จะกลับมามีคะแนนติดลบจำนวนมากและซื้อมาก
James

8
สามารถปรับแต่ง: -1 ถ้าคุณกินขนมที่คนอื่นนำมาด้วย (N-1) ถ้าคุณซื้อขนมอบ ด้วยวิธีนี้หากมีคนโชคดีและซื้อเพียง 4 คนในวันถัดไปบุคคลนั้นจะโชคร้ายและซื้อ 7 คนการซื้อสองครั้งนั้นไม่ได้รับการปฏิบัติอย่างเท่าเทียมกัน -1 เพราะขนมที่คุณซื้อเพื่อตัวเองนั้นเป็นกลาง
James

@ เจมส์ไม่กลัว OP อยู่ในสหรัฐอเมริกาและไม่มีใครในสหรัฐฯเข้าใกล้วันหยุดมากนัก :(
Kyralessa

@ James ใช่นั่นคือการปรับปรุงที่ดี
Gort the Robot

7

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

ฉันยังมีกล่อง มันเริ่มว่างเปล่า ในแต่ละวันก่อนที่จะวาดชื่อฉันจะทิ้งเนื้อหาของกล่องลงในหมวกจากนั้นเข้าไปในกระดาษในหมวกและเอาทุกคนที่จะหายไปในวันพรุ่งนี้ ชื่อของพวกเขาไปในกล่อง

หากถึงเวลาวาดชื่อและหมวกว่างเปล่าฉันจะฉีกกระดาษเพิ่มและเพิ่มชื่อของทุกคนหนึ่งครั้งจากนั้นย้ายชื่อของทุกคนที่จะหายไปในวันพรุ่งนี้

เนื่องจากสองขั้นตอนสุดท้ายนี้เป็นไปได้ที่ชื่อเดียวกันจะอยู่ในหมวกหลายครั้ง หากชื่อที่ฉันวาดมีชื่อเดียวกันกับชื่อบนกระดานฉันจะย้ายกระดาษนั้นไปที่กล่องแล้ววาดอีกครั้ง

ไม่ควรยากเกินไปที่จะแปลระบบนี้เป็นอัลกอริทึมในภาษาที่คุณเลือก


การเรียงผ่านหมวกสำหรับทุกคนที่กำลังจะออกไปดูเหมือนจะเจ็บปวดจริงๆ
Bobson

@ Bobson: คำถามพิเศษบอกว่าขนาดของทีมค่อนข้างเล็ก ถ้าฉันจัดการกับชุดข้อมูลขนาดใหญ่ฉันจะทำสิ่งที่ซับซ้อนกว่านี้
Mason Wheeler

6

อัลกอริทึม, smalgorithm ใช้ฐานข้อมูล

create table team_members 
(
    id integer auto_increment,
    name varchar(255),
    purchase_count integer,
    last_purchase_date datetime,
    present integer,
    prefers_donuts integer default 0,
    primary key( id)
)

ซื้อใคร

select id from team_members where (present = 1) and (prefers_donuts = 0) order by purchase_count, last_purchase_date limit 1;

หลังจากพวกเขาซื้อ:

update team_members set purchase_count = purchase_count + 1, last_purchase_date = now() where id = ?

จากนั้นตั้งค่า:

insert into team_members (name, prefers_donuts) values ('GrandmasterB', 1);

... เพราะฉันเป็นโรงเรียนเก่า

ไม่ควรเป็นการยากเกินไปที่จะเพิ่มการสุ่มโดยการปรับแต่งคำถามแรก - อาจโดยการเพิ่มการสุ่ม () แทนที่จะเรียงลำดับตาม last_purchase วันที่


1
+1 สำหรับการจ้างงานใหม่คุณกำหนดค่าเริ่มต้นpurchase_countให้กับคนอื่นโดยเฉลี่ยหรือไม่
Dan Pichelman

6
อืมคำถามที่ดีมาก นั่นอาจจะใช้ได้ หรือคุณแค่ทำให้คนใหม่พาครัวซองต์ทุกเช้าจนกว่าเขาจะทัน เขาเป็นคนใหม่หลังจากทั้งหมด
GrandmasterB

4

ที่จริงฉันต้องแก้ปัญหานี้บ้างในโลกแห่งความจริง:

remember how many times people have gotten donuts
every day:
  var candidates = everyone
  toss out people who aren't here tomorrow
  toss out people who aren't here today 
  toss out the person who got them today (unless they're the only one left)
  toss out everyone where "times they got donuts"/"times everyone has got donuts"
    is more than 1/number of people (unless that would eliminate everyone)

  pick someone at random from the candidates

สิ่งที่เกิดขึ้นคือคนที่ซื้อโดนัท "มากเกินไป" (เนื่องจากโชคไม่ดีจะไปทำงานเมื่อคนอื่นอยู่ในช่วงวันหยุด ฯลฯ ) ถูกแยกออกจากสระว่ายน้ำจนกว่าการเข้าซื้อกิจการที่เพียงพอจะทำให้พวกเขากลับมาอยู่ภายใต้ การซื้อสินค้า

สิ่งนี้จะต้องมีการขยายเพื่อจัดการกับการจ้างคนใหม่ที่ดีกว่าแม้ว่า ...

อย่างไรก็ตามการออกแบบนี้ทำงานได้ดีสำหรับการเปลี่ยนแปลงตัวแปร (ใครอยู่ใครเป็นใคร) และเมื่อตารางต้องไม่ จำกัด (ในทางปฏิบัติ) ในฐานะโบนัสที่เพิ่มเข้ามาคุณสามารถกำหนดค่าได้อย่างง่ายดายโดยการเพาะ RNG ของคุณ


2

ไม่ดีเท่าคำตอบอื่น ๆ ที่นำเสนอไปแล้ว แต่อีกวิธีหนึ่งในการดูปัญหา:

  1. ทำรายการพนักงานที่เข้าร่วมทั้งหมด
  2. ทำซ้ำรายการหลายครั้ง (พูด 1,000)
  3. สลับรายการ

ทุกบ่ายให้เลือกครัวซองต์ตัวต่อที่มีอยู่ ทุกเช้าครัวซองต์ตัวเงินข้ามชื่อของเขา / เธอออกจากด้านบนของรายการ

การประมวลผลประจำวันทำได้ง่ายด้วยปากกาและกระดาษ

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


ข้อมูลเพิ่มเติม (ต่อคำขอ)

การใช้วิธีการนี้กับรายการแบบยาวคุณจะได้รับประโยชน์จากความโปร่งใส

ไม่เพียง แต่คุณจะรู้ว่าใครจะนำครัวซองต์ในวันพรุ่งนี้ แต่คุณรู้ว่าใครมีกำหนดจะพาพวกเขาในวันรุ่งขึ้นเป็นต้น แน่นอนว่ายิ่งเวลาที่คุณมองว่าแม่นยำน้อยลงเท่าไรคุณก็จะมาจากการขาดเรียน ฯลฯ

ผู้ชื่นชอบการส่อเสียดที่คิดวิธีชั่งน้ำหนักกระดาษในหมวกจะไม่มีโอกาสมากพอที่จะหลีกเลี่ยงหน้าที่นำโดยครัวซองต์

การชักชวนผู้ที่ไม่ใช่ผู้ที่อ้างว่าถูกประมวลผลนั้นสามารถตรวจสอบข้อมูลได้อย่างง่ายดายเกิดข้อสรุปที่ผิดพลาดและสะอื้นต่อไป


1
ยุติ ? Ghenghis Khan อนุมัติโพสต์นี้
Deer Hunter

1
@DeerHunter ฉันไม่ชอบวิธีที่ฝ่ายทรัพยากรบุคคลพูดถึงเสมอเกี่ยวกับ มันทำให้นึกถึงการยิงหมู่ บางทีฉันควรจะพูดว่า "New Hires & Alumni ... " แทน
Dan Pichelman

1

ไม่สุ่ม

รักษารายการสั่งซื้อ หากบุคคลนั้นไม่อยู่ในวันที่พวกเขาควรจะซื้อให้สลับพวกเขากับคนที่มีอยู่ต่อไป ในที่สุดบุคคลนั้นก็จะปรากฏตัวและซื้อซองครัว ดังนั้นเนื้อหาของรายการยังคงเหมือนเดิม แต่บุคคลอาจถูกย้ายหรือขึ้นลงได้

ผู้คนใหม่ ๆ ถูกแทรกเข้าไปในรายการหลังตำแหน่งปัจจุบัน ผู้ที่เลิกหรือยกเลิกจะถูกลบออกจากรายการ ตำแหน่งปัจจุบันเพิ่มขึ้น 1 ทุกวันเมื่อถึงจุดสิ้นสุดตำแหน่งจะกลับไปที่จุดเริ่มต้น

สิ่งนี้ถือว่ามีคนจำนวนมากพอที่จะคิดเวลาที่ไม่มีค่าเฉลี่ยเพื่อส่งเสริมความเป็นธรรม

สุ่ม

เราไม่สามารถเลือกคนสุ่มได้ในแต่ละวันเพราะจะมีอคติระยะสั้นเช่นพลิกเหรียญ 10 ครั้งและคุณสามารถหาหัว 8 และก้อย 2 ได้ดังนั้นหัวจะเมาในระยะสั้น ดังนั้นเราต้องสร้างกลุ่มคนเพื่อให้มันยุติธรรม

ถังจะถูกกำหนดโดยจำนวนครั้งที่มีคนซื้อ crossiants ในอดีต ดังนั้นในกรณีนี้เราจะเก็บพจนานุกรมของผู้คนและซื้อ crossiant ในวันที่ 1 ทุกคนอยู่ในที่ฝากข้อมูลศูนย์ ในขณะที่คนซื้อครัวซองต์พวกเขาจะถูกมอบหมายให้ไปที่ถังถัดไปขึ้นเช่น 1, 2 เป็นต้นส่วนที่สุ่มเลือกมาจากกลุ่มคนที่มีอยู่ในถัง ที่เก็บข้อมูลอันแรกคือที่ที่มีการซื้อน้อยที่สุด หากมีคน 10 คนในที่เก็บของให้เลือกหมายเลขสุ่มจาก 1 ถึง 10 และคนที่ซื้อครัวซองต์ ผู้คนใหม่จะได้รับมอบหมายกลุ่มที่ต่ำที่สุดในปัจจุบันดังนั้นพวกเขาจึงไม่ต้องซื้อ crossiants รอบพิเศษ (แม้ว่าพวกเขาจะอยู่ในกลุ่มผู้ซื้อทันที) หากไม่มีใครอยู่ในกลุ่มฝากข้อมูลระดับต่ำสุด (ไม่มีอยู่ทั้งหมด) ให้ไปที่กลุ่มฝากลำดับถัดไปสูงสุด ตัวอย่างเช่นลอง พูดว่ามีรายชื่อ 10 คน ในวันที่ 8, 8 คนอยู่ในกลุ่มที่ 1 และ 2 อยู่ในกลุ่มที่ 0 คนสองคนในกลุ่มที่ 0 ขาดไป ในกรณีนี้จะใช้ bucket 1 และคนหนึ่งจะอยู่ใน bucket 2 แต่คนจะอยู่ภายในการซื้อ crossiant (ถัง) ภายในกันเพราะคนที่อยู่ใน bucket 2 มักจะไม่อยู่ในนี้ ซื้อพูลสักพัก

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


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