สุ่มตัวอย่างโดยไม่ต้องเปลี่ยน


10

สร้างฟังก์ชั่นที่จะส่งออกชุดตัวเลขสุ่มที่แตกต่างจากช่วง ลำดับขององค์ประกอบในชุดนั้นไม่สำคัญ (สามารถเรียงได้) แต่จะต้องเป็นไปได้สำหรับเนื้อหาของชุดจะแตกต่างกันในแต่ละครั้งที่เรียกใช้ฟังก์ชัน

ฟังก์ชั่นจะได้รับ 3 พารามิเตอร์ตามลำดับที่คุณต้องการ:

  1. จำนวนของตัวเลขในชุดเอาต์พุต
  2. ขีด จำกัด ล่าง (รวม)
  3. ขีด จำกัด บน (รวม)

สมมติว่าตัวเลขทั้งหมดเป็นจำนวนเต็มในช่วง 0 (รวม) ถึง 2 31 (พิเศษ) เอาท์พุทสามารถส่งกลับในแบบที่คุณต้องการ (เขียนถึงคอนโซลเป็นอาร์เรย์ ฯลฯ )

การตัดสิน

เกณฑ์รวมถึง 3 R's

  1. เวลาทำการ - ทดสอบบนเครื่อง Windows 7 แบบ quad-core ด้วยคอมไพเลอร์สิ่งใดก็ได้ที่เป็นอิสระหรือใช้งานง่าย
  2. ความทนทาน - ฟังก์ชั่นการจัดการกรณีมุมหรือมันจะตกอยู่ในวงไม่ จำกัด หรือผลลัพธ์ที่ไม่ถูกต้อง - ข้อยกเว้นหรือข้อผิดพลาดในการป้อนข้อมูลที่ไม่ถูกต้อง
  3. การสุ่ม - ควรสร้างผลลัพธ์แบบสุ่มที่ไม่สามารถคาดเดาได้ง่ายด้วยการแจกแจงแบบสุ่ม การใช้ตัวสร้างตัวเลขสุ่มในตัวนั้นใช้ได้ แต่ไม่ควรมีอคติที่ชัดเจนหรือรูปแบบการทำนายที่ชัดเจน จำเป็นต้องดีกว่าตัวสร้างตัวเลขสุ่มที่ใช้โดยแผนกบัญชีใน Dilbert

ถ้ามันแข็งแกร่งและสุ่มมันจะลงมาเพื่อรันไทม์ ความล้มเหลวที่จะแข็งแกร่งหรือสุ่มเจ็บอันดับของ


เอาต์พุตควรผ่านบางอย่างเช่นการทดสอบDIEHARDหรือTestU01หรือคุณจะตัดสินการสุ่มของมันอย่างไร โอ้และรหัสควรทำงานในโหมด 32 หรือ 64 บิต? (นั่นจะทำให้เกิดความแตกต่างอย่างมากสำหรับการปรับให้เหมาะสม)
Ilmari Karonen

ฉันคิดว่า TestU01 ค่อนข้างรุนแรง หลักเกณฑ์ที่ 3 แสดงถึงการกระจายตัวที่สม่ำเสมอหรือไม่? นอกจากนี้ทำไมความต้องการที่ไม่เกิดซ้ำ นั่นไม่ใช่การสุ่มโดยเฉพาะ
Joey

@ โจอี้แน่นอน มันเป็นการสุ่มแบบสุ่มโดยไม่มีการแทนที่ ตราบใดที่ไม่มีใครอ้างว่าตำแหน่งต่าง ๆ ในรายการเป็นตัวแปรสุ่มอิสระไม่มีปัญหา
Peter Taylor

อ่าแน่นอน แต่ฉันไม่แน่ใจว่ามีห้องสมุดและเครื่องมือที่มีชื่อเสียงในการวัดการสุ่มตัวอย่าง :-) หรือไม่
Joey

@IlmariKaronen: RE: Randomness: ฉันเคยเห็นการใช้งานมาก่อนแล้วว่าไม่ได้สุ่มตัวอย่าง ไม่ว่าพวกเขาจะมีอคติหนักหรือขาดความสามารถในการสร้างผลลัพธ์ที่แตกต่างในการวิ่งติดต่อกัน ดังนั้นเราจะไม่พูดสุ่มระดับการเข้ารหัสลับ แต่สุ่มมากกว่าเครื่องกำเนิดไฟฟ้าจำนวนของกรมบัญชีสุ่ม Dilbert
Jim McKeeth

คำตอบ:


6

หลาม

import random

def sample(n, lower, upper):
    result = []
    pool = {}
    for _ in xrange(n):
        i = random.randint(lower, upper)
        x = pool.get(i, i)
        pool[i] = pool.get(lower, lower)
        lower += 1
        result.append(x)
    return result

ฉันอาจเพิ่งคิดค้นอัลกอริทึมที่รู้จักกันดีอีกครั้ง แต่ความคิดคือการ (conceptually) ทำการสับเปลี่ยน Fisher-Yates บางส่วนของช่วงlower..upperเพื่อให้ได้nคำนำหน้าความยาวของช่วงสับที่สม่ำเสมอ

แน่นอนการจัดเก็บช่วงทั้งหมดจะค่อนข้างแพงดังนั้นฉันเก็บเฉพาะสถานที่ที่มีการสลับองค์ประกอบ

ด้วยวิธีนี้อัลกอริทึมควรทำงานได้ดีทั้งในกรณีที่คุณสุ่มตัวอย่างตัวเลขจากช่วงแคบ ๆ (เช่น 1,000 หมายเลขในช่วง 1..1000) รวมถึงกรณีที่คุณสุ่มตัวอย่างตัวเลขจากช่วงขนาดใหญ่ .

ฉันไม่แน่ใจเกี่ยวกับคุณภาพของการสุ่มจากตัวสร้างใน Python แต่มันค่อนข้างง่ายที่จะสลับในตัวสร้างใด ๆ ที่สามารถสร้างจำนวนเต็มสม่ำเสมอจากบางช่วง


1
Python ใช้Mersenne Twisterดังนั้นจึงค่อนข้างดี
ESultanik

1

หลาม 2.7

import random
print(lambda x,y,z:random.sample(xrange(y,z),x))(input(),input(),input())

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

แก้ไข: เพิ่งสังเกตเห็นว่าช่วง () ไม่ต้องการสร้างรายการใหญ่ ส่งผลให้เกิดข้อผิดพลาดของหน่วยความจำ จะดูว่ามีวิธีอื่นที่จะทำเช่นนี้ ...

edit2: range เป็นฟังก์ชั่นที่ไม่ถูกต้อง xrange ทำงาน จำนวนเต็มสูงสุดจริง ๆ แล้ว2**31-1สำหรับไพ ธ อน

ทดสอบ:

python sample.py
10
0
2**31-1
[786475923, 2087214992, 951609341, 1894308203, 173531663, 211170399, 426989602, 1909298419, 1424337410, 2090382873]

1

ส่งคืนอาร์เรย์ที่มี ints สุ่ม x ที่ไม่ซ้ำกันระหว่าง min และ max (ผู้โทรต้องเป็นอิสระ)

#include <stdlib.h>
#include <stdint.h>
#define MAX_ALLOC ((uint32_t)0x40000000)  //max allocated bytes, fix per platform
#define MAX_SAMPLES (MAX_ALLOC/sizeof(uint32_t))

int* randsamp(uint32_t x, uint32_t min, uint32_t max)
{
   uint32_t r,i=x,*a;
   if (!x||x>MAX_SAMPLES||x>(max-min+1)) return NULL;
   a=malloc(x*sizeof(uint32_t));
   while (i--) {
      r= (max-min+1-i);
      a[i]=min+=(r ? rand()%r : 0);
      min++;
   }
   while (x>1) {
      r=a[i=rand()%x--];
      a[i]=a[x];
      a[x]=r;
   }
   return a;
}

ทำงานโดยการสร้างจำนวนเต็ม x ตามลำดับแบบสุ่มในช่วงจากนั้นจึงทำการสับ เพิ่มseed(time)ผู้โทรเข้าที่อื่นถ้าคุณไม่ต้องการผลลัพธ์เดียวกันทุกครั้ง




1

คำถามไม่ถูกต้อง คุณต้องการสุ่มตัวอย่างแบบสม่ำเสมอหรือไม่? ในกรณีที่จำเป็นต้องมีการสุ่มตัวอย่างสม่ำเสมอฉันมีรหัสต่อไปนี้ใน R ซึ่งมีความซับซ้อนโดยเฉลี่ยO ( s log s ) โดยที่sคือขนาดตัวอย่าง

# The Tree growing algorithm for uniform sampling without replacement
# by Pavel Ruzankin 
quicksample = function (n,size)
# n - the number of items to choose from
# size - the sample size
{
  s=as.integer(size)
  if (s>n) {
    stop("Sample size is greater than the number of items to choose from")
  }
  # upv=integer(s) #level up edge is pointing to
  leftv=integer(s) #left edge is poiting to; must be filled with zeros
  rightv=integer(s) #right edge is pointig to; must be filled with zeros
  samp=integer(s) #the sample
  ordn=integer(s) #relative ordinal number

  ordn[1L]=1L #initial value for the root vertex
  samp[1L]=sample(n,1L) 
  if (s > 1L) for (j in 2L:s) {
    curn=sample(n-j+1L,1L) #current number sampled
    curordn=0L #currend ordinal number
    v=1L #current vertice
    from=1L #how have come here: 0 - by left edge, 1 - by right edge
    repeat {
      curordn=curordn+ordn[v]
      if (curn+curordn>samp[v]) { #going down by the right edge
        if (from == 0L) {
          ordn[v]=ordn[v]-1L
        }
        if (rightv[v]!=0L) {
          v=rightv[v]
          from=1L
        } else { #creating a new vertex
          samp[j]=curn+curordn
          ordn[j]=1L
          # upv[j]=v
          rightv[v]=j
          break
        }
      } else { #going down by the left edge
        if (from==1L) {
          ordn[v]=ordn[v]+1L
        }
        if (leftv[v]!=0L) {
          v=leftv[v]
          from=0L
        } else { #creating a new vertex
          samp[j]=curn+curordn-1L
          ordn[j]=-1L
          # upv[j]=v
          leftv[v]=j
          break
        }
      }
    }
  }
  return(samp)  
}

แน่นอนหนึ่งอาจเขียนใหม่ใน C เพื่อประสิทธิภาพที่ดีขึ้น ความซับซ้อนของอัลกอริทึมนี้ถูกกล่าวถึงใน: Rouzankin, PS; Voytishek, AV ค่าใช้จ่ายของอัลกอริทึมสำหรับการเลือกแบบสุ่ม วิธีการ Monte Carlo 5 (1999) เลขที่ 1, 39-54 http://dx.doi.org/10.1515/mcma.1999.5.1.39

คุณอาจพิจารณาบทความนี้เพื่อหาอัลกอริทึมอื่นที่มีความซับซ้อนโดยเฉลี่ยเท่ากัน

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

ดูเพิ่มเติมที่การสุ่มตัวอย่างแบบสม่ำเสมอ: P. Gupta, GP Bhattacharjee (1984) อัลกอริทึมที่มีประสิทธิภาพสำหรับการสุ่มตัวอย่างแบบไม่มีการแทนที่ วารสารคณิตศาสตร์คอมพิวเตอร์ระหว่างประเทศ 16: 4, หน้า 201-209 DOI: 10.1080 / 00207168408803438

Teuhola, J. และ Nevalainen, O. 1982. อัลกอริธึมที่มีประสิทธิภาพสองวิธีสำหรับการสุ่มตัวอย่างแบบสุ่มโดยไม่มีการแทนที่ / IJCM /, 11 (2): 127–140 DOI: 10.1080 / 00207168208803304

ในบทความล่าสุดผู้เขียนใช้ตารางแฮชและอ้างว่าอัลกอริทึมของพวกเขามีความซับซ้อนO ( s ) มีอัลกอริทึมตารางแฮชที่รวดเร็วกว่าหนึ่งซึ่งจะนำมาใช้ใน pqR (ค่อนข้างเร็ว R): https://stat.ethz.ch/pipermail/r-devel/2017-October/075012.html


1

APL, 18 22 ไบต์

{⍵[0]+(1↑⍺)?⍵[1]-⍵[0]}

ประกาศฟังก์ชั่นที่ไม่ระบุชื่อที่จะใช้เวลาสองมีปากเสียงและ คือจำนวนตัวเลขสุ่มที่คุณต้องการคือเวกเตอร์ที่มีขอบเขตล่างและบนตามลำดับนั้น

a?bเลือกaสุ่มตัวเลขระหว่าง 0- bโดยไม่ต้องเปลี่ยน โดยการที่⍵[1]-⍵[0]เราได้รับขนาดช่วง จากนั้นเราจะเลือกตัวเลข (ดูด้านล่าง) จากช่วงนั้นและเพิ่มขอบเขตล่าง ใน C นี่จะเป็น

lower + rand() * (upper - lower)

ครั้งโดยไม่ต้องเปลี่ยน ไม่ต้องใช้วงเล็บใน APL ทำงานจากขวาไปซ้าย

สมมติว่าฉันเข้าใจเงื่อนไขอย่างถูกต้องแล้วสิ่งนี้จะไม่ผ่านเกณฑ์ 'ความทนทาน' เนื่องจากฟังก์ชันจะล้มเหลวหากมีการขัดแย้งที่ไม่เหมาะสม (เช่นการส่งเวกเตอร์แทนที่จะเป็นสเกลาร์เป็น)

ในกรณีที่เป็นเวกเตอร์มากกว่าเกลา, เตะองค์ประกอบแรกของ1↑⍺ สำหรับเซนต์คิตส์และเนวิสนี่คือสเกลาร์นั้น สำหรับเวกเตอร์มันเป็นองค์ประกอบแรก สิ่งนี้จะทำให้ฟังก์ชั่นตรงตามเกณฑ์ 'ความทนทาน'

ตัวอย่าง:

Input: 100 {⍵[0]+⍺?⍵[1]-⍵[0]} 0 100
Output: 34 10 85 2 46 56 32 8 36 79 77 24 90 70 99 61 0 21 86 50 83 5 23 27 26 98 88 66 58 54 76 20 91 72 71 65 63 15 33 11 96 60 43 55 30 48 73 75 31 13 19 3 45 44 95 57 97 37 68 78 89 14 51 47 74 9 67 18 12 92 6 49 41 4 80 29 82 16 94 52 59 28 17 87 25 84 35 22 38 1 93 81 42 40 69 53 7 39 64 62

2
นี่ไม่ใช่การเขียนโค้ด แต่เป็นวิธีการที่เร็วที่สุดดังนั้นเป้าหมายคือการสร้างรหัสที่เร็วที่สุดในการทำงานแทนที่จะเป็นรหัสที่สั้นที่สุด อย่างไรก็ตามคุณไม่จำเป็นต้องเลือกไอเท็มจากอาร์กิวเมนต์เช่นนั้นและคุณสามารถกำหนดลำดับของมันได้ดังนั้น{⍵+⍺?⎕-⍵}ควรจะพอเพียงโดยที่ prompt สำหรับอาร์จขอบบนและอาร์คขวาจะต่ำกว่า
Uriel

0

สกาล่า

object RandSet {
  val random = util.Random 

  def rand (count: Int, lower: Int, upper: Int, sofar: Set[Int] = Set.empty): Set[Int] =
    if (count == sofar.size) sofar else 
    rand (count, lower, upper, sofar + (random.nextInt (upper-lower) + lower)) 
}

object RandSetRunner {

  def main (args: Array [String]) : Unit = {
    if (args.length == 4) 
      (0 until args (0).toInt).foreach { unused => 
      println (RandSet.rand (args (1).toInt, args (2).toInt, args (3).toInt).mkString (" "))
    }
    else Console.err.println ("usage: scala RandSetRunner OUTERCOUNT COUNT MIN MAX")
  }
}

รวบรวมและเรียกใช้:

scalac RandSetRunner.scala 
scala RandSetRunner 200 15 0 100

บรรทัดที่สองจะเรียกใช้การทดสอบ 200 รายการโดยมีค่า 15 ค่าจาก 0 ถึง 100 เนื่องจาก Scala สร้างรหัสไบต์ที่รวดเร็ว แต่ต้องการเวลาเริ่มต้นบางส่วน ดังนั้น 200 เริ่มต้นด้วย 15 ค่าจาก 0 ถึง 100 จะใช้เวลามากขึ้น

ตัวอย่างแกนเดี่ยว 2 Ghz:

time scala RandSetRunner 100000 10 0 1000000 > /dev/null

real    0m2.728s
user    0m2.416s
sys     0m0.168s

ตรรกะ:

ใช้ build-in แบบสุ่มและเลือกหมายเลขซ้ำในช่วง (max-min) เพิ่ม min และตรวจสอบถ้าขนาดของชุดเป็นขนาดที่คาดหวัง

วิจารณ์:

  • มันจะเร็วสำหรับกลุ่มตัวอย่างขนาดเล็กที่มีช่วงขนาดใหญ่ แต่หากภารกิจต้องเลือกองค์ประกอบทั้งหมดของกลุ่มตัวอย่าง (999 หมายเลขจาก 1,000) กลุ่มนั้นจะเลือกหมายเลขซ้ำ ๆ อยู่ในชุดแล้ว
  • จากคำถามที่ฉันไม่แน่ใจว่าฉันจะต้องฆ่าเชื้อกับคำขอที่ไม่สามารถบรรลุได้เช่นรับ 10 ตัวเลขที่แตกต่างจาก 4 ถึง 8 ตอนนี้จะนำไปสู่การวนรอบที่ไม่มีที่สิ้นสุด แต่สามารถหลีกเลี่ยงได้อย่างง่ายดายด้วยการตรวจสอบก่อน ร้องขอ

0

โครงการ

ไม่แน่ใจว่าทำไมคุณต้องผ่านพารามิเตอร์ 3 ตัวและทำไมฉันต้องสมมติช่วงใด ๆ ...

(import srfi-1) ;; for iota
(import srfi-27) ;; randomness
(import srfi-43) ;; for vector-swap!

(define rand (random-source-make-integers
               default-random-source))

;; n: length, i: lower limit
(define (random-range n i)
  (let ([v (list->vector (iota n i))])
    (let f ([n n])
      (let* ([i (rand n)] [n (- n 1)])
        (if (zero? n) v
            (begin (vector-swap! v n i) (f n)))))))

0

R

random <- function(count, from, to) {
  rand.range <- to - from

  vec <- c()

  for (i in 1:count) {
    t <- sample(rand.range, 1) + from
    while(i %in% vec) {
      t <- sample(rand.range, 1) + from
    }
    vec <- c(vec, t)
  }

  return(vec)
}

0

C ++

รหัสนี้ดีที่สุดเมื่อวาดตัวอย่างจำนวนมากจากช่วง

#include <exception>
#include <stdexcept>
#include <cstdlib>

template<typename OutputIterator>
 void sample(OutputIterator out, int n, int min, int max)
{
  if (n < 0)
    throw std::runtime_error("negative sample size");
  if (max < min)
    throw std::runtime_error("invalid range");
  if (n > max-min+1)
    throw std::runtime_error("sample size larger than range");

  while (n>0)
  {
    double r = std::rand()/(RAND_MAX+1.0);
    if (r*(max-min+1) < n)
    {
      *out++ = min;
      --n;
    }
    ++min;
  }
}

นี้สามารถได้รับการติดอยู่ในวง จำกัด เว้นแต่มีขนาดใหญ่กว่าmax-min nนอกจากนี้ลำดับเอาต์พุตยังเพิ่มขึ้นแบบซ้ำซากดังนั้นคุณจะได้รับการสุ่มคุณภาพต่ำมาก แต่ก็ยังจ่ายค่าใช้จ่ายในการโทรrand()หลายครั้งต่อผลลัพธ์ สุ่มสับเปลี่ยนของอาเรย์อาจจะคุ้มค่ากับเวลาทำงานพิเศษ
Peter Cordes

0

Q (19 ตัวอักษร)

f:{(neg x)?y+til z}

จากนั้นใช้ f [x; y; z] เป็น [นับตัวเลขในชุดผลลัพธ์จุดเริ่มต้นขนาดของช่วง]

เช่น f [5; 10; 10] จะเอาท์พุท 5 ตัวเลขสุ่มที่แตกต่างกันระหว่าง 10 ถึง 19

q)\ts do[100000;f[100;1;10000]]
2418 131456j

ผลลัพธ์ด้านบนแสดงประสิทธิภาพที่ 100,000 ซ้ำของการเลือก 100 ตัวเลขสุ่มระหว่าง 1 และ 10,000


0

R, 31 หรือ 40 ไบต์ (ขึ้นอยู่กับความหมายของคำว่า "ช่วง")

หากอินพุตมี 3 ตัวเลขa[1], a[2], a[3]และตาม“ ช่วง” คุณหมายถึง“ ลำดับเลขจำนวนเต็มจาก [2] ถึง [3]” แสดงว่าคุณมีสิ่งนี้:

a=scan();sample(a[2]:a[3],a[1])

หากคุณมีอาร์เรย์nที่คุณต้องการสุ่มตัวอย่างอีกครั้ง แต่ภายใต้ข้อ จำกัด ของข้อ จำกัด ด้านล่างและด้านบนเช่น "ค่าตัวอย่างของอาร์เรย์ที่กำหนดnจากช่วงa[1]...a[2]" ให้ใช้วิธีนี้:

a=scan();sample(n[n>=a[2]&n<=a[3]],a[1])

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

  • ความทนทาน: กรณีมุม (ลำดับของความยาวเดียวกันกับช่วงตัวอย่าง) ได้รับการจัดการโดยค่าเริ่มต้น
  • เวลาทำงาน: รวดเร็วมากเพราะสร้างขึ้น
  • การสุ่ม: เมล็ดจะเปลี่ยนโดยอัตโนมัติทุกครั้งที่เรียกใช้ RNG

อย่างน้อยในเครื่องของฉัน0:(2^31)ทำให้เกิดError: cannot allocate a vector of size 16.0 Gb
Giuseppe

@Giuseppe เมื่อเร็ว ๆ นี้ฉันได้ทำงานกับปัญหาหน่วยความจำขนาดใหญ่และวิธีการแก้ปัญหาที่เป็นจริง ... ใช้มันบนเครื่องที่ดีกว่า ข้อ จำกัด ในการกำหนดงานเกี่ยวข้องกับตัวประมวลผลไม่ใช่หน่วยความจำดังนั้น ... การละเมิดกฎหรือไม่ อาฉันเป็นคนโง่ ฉันคิดว่ามันเป็นความท้าทายของรหัสกอล์ฟแต่จริงๆแล้วมันเป็น ... รหัสที่เร็วที่สุด ฉันแพ้ฉันเดาได้ไหม
Andreï Kostyrka

0

Javascript (ใช้ไลบรารีภายนอก) (64 ไบต์ / 104 ไบต์ ??)

(a,b,n)=>_.Range(0,n).Select(x=>Math.random()*(b-a)+a).ToArray()

ลิงก์ไปยัง lib: https://github.com/mvegh1/Enumerable/

คำอธิบายรหัส: การแสดงออกของแลมบ์ดายอมรับ min, max, count เป็น args สร้างคอลเลกชันขนาด n และจับคู่แต่ละองค์ประกอบเข้ากับตัวเลขสุ่มที่เหมาะสมกับเกณฑ์ขั้นต่ำ / สูงสุด แปลงเป็นอาร์เรย์ JS ดั้งเดิมและส่งคืน ฉันวิ่งสิ่งนี้ด้วยขนาด 5,000,000 และหลังจากใช้การแปลงที่แตกต่างยังคงมีองค์ประกอบ 5,000,000 หากมีการตกลงกันว่าสิ่งนี้ไม่ปลอดภัยเพียงพอสำหรับการรับประกันความชัดเจนฉันจะอัปเดตคำตอบ

ฉันรวมสถิติบางอย่างในภาพด้านล่าง ...

ป้อนคำอธิบายรูปภาพที่นี่

แก้ไข: ภาพด้านล่างแสดงรหัส / ประสิทธิภาพที่รับประกันทุกองค์ประกอบจะแตกต่างกัน มันช้ากว่ามาก (6.65 วินาทีสำหรับองค์ประกอบ 50,000 ชิ้น) เทียบกับรหัสต้นฉบับด้านบนสำหรับ args เดียวกัน (0.012 วินาที)

ป้อนคำอธิบายรูปภาพที่นี่


0

K (oK) , 14 ไบต์

สารละลาย:

{y+(-x)?1+z-y}

ลองออนไลน์!

ตัวอย่าง:

> {y+(-x)?1+z-y}. 10 10 20      / note: there are two ways to provide input, dot or
13 20 16 17 19 10 14 12 11 18
> {y+(-x)?1+z-y}[10;10;20]      / explicitly with [x;y;z]
12 11 13 19 15 17 18 20 14 10

คำอธิบาย:

ใช้ 3 อินพุตโดยนัยต่อข้อมูลจำเพาะ:

  • xนับจำนวนตัวเลขในชุดเอาต์พุต
  • yขีด จำกัด ล่าง (รวม)
  • zขีด จำกัด บน (รวม)

{y+(-x)?1+z-y} / the solution
{            } / lambda function with x, y and z as implicit inputs
          z-y  / subtract lower limit from upper limit
        1+     / add 1
   (-x)?       / take x many distinct items from 0..(1+z=y)
 y+            / add lower limit

หมายเหตุ:

นอกจากนี้ยังมีหลายภาษาq/kdb+พร้อมชุดวงเล็บพิเศษ: {y+((-)x)?1+z-y}(16 ไบต์)


0

ความจริง + ห้องสมุด

f(n:PI,a:INT,b:INT):List INT==
    r:List INT:=[]
    a>b or n>99999999 =>r
    d:=1+b-a
    for i in 1..n repeat
          r:=concat(r,a+random(d)$INT)
    r

ฟังก์ชัน f () ข้างต้นกลับเป็นข้อผิดพลาดในรายการที่ว่างเปล่าในกรณี f (n, a, b) ด้วย> b ในกรณีอื่น ๆ ของการป้อนข้อมูลที่ไม่ถูกต้องจะไม่ทำงานด้วยข้อความแสดงข้อผิดพลาดหนึ่งข้อความในหน้าต่าง Axiom เนื่องจากอาร์กิวเมนต์จะไม่ใช่ประเภทที่ถูกต้อง ตัวอย่าง

(6) -> f(1,1,5)
   (6)  [2]
                                                       Type: List Integer
(7) -> f(1,1,1)
   (7)  [1]
                                                       Type: List Integer
(10) -> f(10,1,1)
   (10)  [1,1,1,1,1,1,1,1,1,1]
                                                       Type: List Integer
(11) -> f(10,-20,-1)
   (11)  [- 10,- 4,- 18,- 5,- 5,- 11,- 15,- 1,- 20,- 1]
                                                       Type: List Integer
(12) -> f(10,-20,-1)
   (12)  [- 4,- 5,- 3,- 4,- 18,- 1,- 2,- 14,- 19,- 8]
                                                       Type: List Integer
(13) -> f(10,-20,-1)
   (13)  [- 18,- 12,- 12,- 19,- 19,- 15,- 5,- 17,- 19,- 4]
                                                       Type: List Integer
(14) -> f(10,-20,-1)
   (14)  [- 8,- 11,- 20,- 10,- 4,- 8,- 11,- 3,- 10,- 16]
                                                       Type: List Integer
(15) -> f(10,9,-1)
   (15)  []
                                                       Type: List Integer
(16) -> f(10,0,100)
   (16)  [72,83,41,35,27,0,33,18,60,38]
                                                       Type: List Integer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.