TIO पर जावा 7+, n = 50 ~ 30 सेकंड में
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.Random;
class Main{
public static void main(String[] a){
int n=50;
Random randomGenerator = new Random();
int i = n+1;
int squaredN = n*n;
int[]randomIntegers = new int[i];
randomIntegers[n] = squaredN;
while(true){
for(i=n; i-->1; ){
randomIntegers[i] = randomGenerator.nextInt(squaredN);
}
Set<Integer> result = new HashSet<>();
Arrays.sort(randomIntegers);
for(i=n; i-->0; ){
result.add(randomIntegers[i+1] - randomIntegers[i]);
}
if(!result.contains(0) && result.size()==n){
System.out.println(result);
return;
}
}
}
}
इस चुनौती के कोड-गोल्फ संस्करण के लिए मेरे जवाब का अब तक का केवल अनौपचारिक संस्करण , केवल एक मामूली बदलाव के साथ: श्रेणी में पूर्णांक java.util.Random#nextInt(limit)
के (int)(Math.random()*limit)
लिए उपयोग किया जाता है [0, n)
, क्योंकि यह लगभग दोगुना है ।
इसे ऑनलाइन आज़माएं।
स्पष्टीकरण:
दृष्टिकोण का इस्तेमाल किया:
कोड दो भागों में विभाजित है:
n
रैंडम पूर्णांकों की राशि की एक सूची बनाएं जो कि योग है n squared
।
- तब यह जांचता है कि क्या सभी मूल्य अद्वितीय हैं और कोई भी शून्य नहीं है, और यदि या तो गलत है, तो यह फिर से चरण 1 की कोशिश करेगा, जब तक हमारे पास परिणाम नहीं होगा तब तक दोहराते और दोहराते रहें।
चरण 1 निम्नलिखित उप-चरणों के साथ किया जाता है:
1) n-1
रेंज में यादृच्छिक पूर्णांकों की मात्रा का एक सरणी उत्पन्न करते हैं [0, n squared)
। और इस सूची में जोड़ें 0
और n squared
। यह O(n+1)
प्रदर्शन में किया जाता है ।
2) फिर यह बिलियन के साथ सरणी को सॉर्ट करेगा java.util.Arrays.sort(int[])
, यह O(n*log(n))
प्रदर्शन में किया जाता है , जैसा कि डॉक्स में बताया गया है:
संख्यात्मक क्रम में आरोही की निर्दिष्ट सरणी को सॉर्ट करता है। सॉर्टिंग एल्गोरिथ्म एक ट्यून किया गया क्विकॉर्ट है, जो जॉन एल। बेंटले और एम। डगलस मैकलियर के "इंजीनियरिंग ए सॉर्ट फंक्शन", सॉफ्टवेयर-प्रैक्टिस और एक्सपीरियंस, वॉल्यूम से लिया गया है। 23 (11) पी। 1249-1265 (नवंबर 1993)। यह एल्गोरिथ्म कई डेटा सेट पर n * लॉग (n) प्रदर्शन प्रदान करता है जो अन्य क्विकॉर्ट्स को द्विघात प्रदर्शन को नीचा दिखाने का कारण बनता है।
3) प्रत्येक जोड़ी के बीच अंतर की गणना करें। अंतर की इस परिणामी सूची में n
पूर्णांकों के योग होंगे जो योग करते हैं n squared
। यह O(n)
प्रदर्शन में किया जाता है ।
यहाँ एक उदाहरण है:
// n = 4, nSquared = 16
// n-1 amount of random integers in the range [0, nSquared):
[11, 2, 5]
// Add 0 and nSquared to it, and sort:
[0, 2, 5, 11, 16]
// Calculate differences:
[2, 3, 6, 5]
// The sum of these differences will always be equal to nSquared
sum([2, 3, 6, 5]) = 16
तो ऊपर दिए गए ये तीन चरण प्रदर्शन के लिए बहुत अच्छे हैं, चरण 2 के विपरीत और पूरी चीज़ के चारों ओर लूप, जो एक बुनियादी जानवर-बल है। चरण 2 इन उप-चरणों में विभाजित है:
1) अंतर सूची पहले से ही में सहेजी गई है java.util.Set
। यह जांच करेगा कि क्या इस सेट का आकार बराबर है n
। यदि ऐसा है, तो इसका मतलब है कि हमारे द्वारा उत्पन्न सभी यादृच्छिक मूल्य अद्वितीय हैं।
2) और यह भी जाँच करेगा कि यह कोई शामिल है 0
के बाद से चुनौती रेंज में यादृच्छिक मान के लिए पूछता है, सेट में [1, X]
, जहां X
है n squared
शून्य से की राशि [1, ..., n-1]
के रूप में द्वारा कहा गया, @Skidsdev नीचे टिप्पणी में।
यदि उपरोक्त दोनों विकल्पों में से कोई भी (सभी मान अद्वितीय नहीं हैं, या एक शून्य मौजूद है), तो यह चरण 1 पर रीसेट करके एक नया सरणी उत्पन्न करेगा और फिर सेट करेगा। यह तब तक जारी रहता है जब तक कि हमारे पास कोई परिणाम न हो। इस वजह से, समय काफी भिन्न हो सकता है। मैंने इसे TIO पर एक बार 3 सेकंड में पूरा करने के लिए देखा है n=50
, लेकिन एक बार के लिए 55 सेकंड में भी n=50
।
एकरूपता साबित करें:
मुझे पूरी तरह से यकीन नहीं है कि इसे पूरी तरह से ईमानदार कैसे साबित किया जाए। java.util.Random#nextInt
के रूप में डॉक्स में वर्णन किया गया है, यकीन है कि के लिए एक समान है:
int
इस यादृच्छिक संख्या जनरेटर के अनुक्रम से समान रूप से वितरित अगले छद्म आयामी, लौटाता है । इसका सामान्य अनुबंध nextInt
यह है कि एक int
मान छद्म रूप से उत्पन्न होता है और वापस लौटता है। सभी 2 32 संभावित int
मानों (लगभग) समान संभावना के साथ उत्पादन किया जाता है।
इन (छांटे गए) यादृच्छिक मूल्यों के बीच अंतर निश्चित रूप से एक समान नहीं है, लेकिन एक पूरे के रूप में सेट समान हैं। फिर, मुझे यकीन नहीं है कि इसे गणितीय रूप से कैसे साबित किया जाए, लेकिन यहां एक स्क्रिप्ट है जो काउंटर के साथ मैप में 10,000
उत्पन्न सेट (के लिए n=10
) डाल देगा , जहां अधिकांश सेट अद्वितीय हैं; कुछ दो बार दोहराया; और अधिकतम बार-बार होने वाली घटना सीमा में है [4,8]
।
स्थापाना निर्देश:
चूँकि जावा कोड को बनाने और चलाने के बारे में बहुत सारी जानकारी उपलब्ध है, इसलिए जावा एक बहुत ही जानी-मानी भाषा है, इसलिए मैं इसे छोटा रखूँगा।
मेरे कोड में उपयोग किए जाने वाले सभी उपकरण जावा 7 (शायद पहले से ही जावा 5 या 6 में उपलब्ध हैं, लेकिन चलो केवल 7 का उपयोग करें)। मुझे पूरा यकीन है कि जावा 7 पहले से ही संग्रहीत है, इसलिए मैं अपना कोड चलाने के लिए जावा 8 डाउनलोड करने का सुझाव दूंगा।
सुधार के बारे में विचार:
मैं शून्य के लिए चेक के लिए एक सुधार खोजना चाहता हूं और सभी मान अद्वितीय हैं। मैं 0
पहले से जांच कर सकता था , यह सुनिश्चित करने के लिए कि हम जिस यादृच्छिक मान को जोड़ते हैं, वह सरणी में पहले से ही नहीं है, लेकिन इसका मतलब होगा कि कुछ चीजें: सरणी एक होनी चाहिए ArrayList
ताकि हम बिलिन पद्धति का उपयोग कर सकें .contains
; थोड़ी देर के लूप को तब तक जोड़ा जाना चाहिए जब तक हमें एक यादृच्छिक मान नहीं मिल जाता है जो अभी तक सूची में नहीं है। चूंकि शून्य के लिए जाँच अब .contains(0)
सेट पर की जाती है (जो केवल एक बार जाँच की जाती है), यह उस बिंदु पर जाँच करने के लिए प्रदर्शन के लिए सबसे बेहतर है .contains
, सूची में लूप को जोड़ने की तुलना में , जिसे कम से कम n
बार चेक किया जाएगा , लेकिन सबसे अधिक संभावना है।
विशिष्टता की जांच के लिए, हमारे पास केवल n
यादृच्छिक पूर्णांकों की राशि है n squared
जो कार्यक्रम के चरण 1 के बाद योग करते हैं , इसलिए केवल तभी हम जांच सकते हैं कि सभी अद्वितीय हैं या नहीं। सरणी के बजाय एक छांटने योग्य सूची रखना और बीच में अंतर की जांच करना संभव हो सकता है, लेकिन मुझे गंभीरता से संदेह है कि यह प्रदर्शन को सुधारने से बेहतर होगा कि उन्हें एक में डाल दिया जाए Set
और जांचें कि क्या उस सेट का आकार n
एक बार है।