একটি ইনপুটটিতে চক্রীয় শব্দের সংখ্যা গণনা করুন


9

চক্রীয় শব্দ

সমস্যা বিবৃতি

আমরা একটি চক্রাকার শব্দটিকে একটি বৃত্তে লেখা শব্দ হিসাবে ভাবতে পারি। একটি চক্রীয় শব্দটি উপস্থাপনের জন্য, আমরা একটি স্বেচ্ছাসেবী শুরুর অবস্থান চয়ন করি এবং ঘড়ির কাঁটার ক্রমে অক্ষরগুলি পড়ি। সুতরাং, "চিত্র" এবং "টিউরিপিক" একই চক্রীয় শব্দের উপস্থাপনা।

আপনাকে একটি স্ট্রিং [] শব্দ দেওয়া হয়েছে, যার প্রতিটি উপাদান একটি চক্রীয় শব্দের উপস্থাপনা। উপস্থাপন করা হয় এমন বিভিন্ন চক্রীয় শব্দের সংখ্যাটি ফিরিয়ে দিন।

দ্রুততম জয় (বিগ ও, যেখানে একটি স্ট্রিংয়ের অক্ষরের সংখ্যা)


3
আপনি যদি নিজের কোডটির সমালোচনা খুঁজছেন তবে যাওয়ার জায়গাটি কোডেরিউ.স্ট্যাকেক্সেক্সঞ্জ.কম।
পিটার টেলর

কুল। আমি চ্যালেঞ্জের উপর জোর দেওয়ার জন্য সম্পাদনা করব এবং সমালোচনা অংশটি কোড পর্যালোচনাতে স্থানান্তর করব। ধন্যবাদ পিটার
দ্য ইগনলেগস

1
জয়ের মানদণ্ড কী? সবচেয়ে সংক্ষিপ্ত কোড (কোড গল্ফ) বা অন্য কিছু? ইনপুট এবং আউটপুট আকারে কোন সীমাবদ্ধতা আছে? আমাদের কি কোনও ফাংশন বা একটি সম্পূর্ণ প্রোগ্রাম লেখার দরকার আছে? এটি কি জাভাতে থাকতে হবে?
ugoren

1
@ ইগগনলেগস আপনি বিগ-ও নির্দিষ্ট করেছেন - তবে কোন প্যারামিটারের সাথে সম্মতি রেখেছেন? অ্যারে স্ট্রিং সংখ্যা? স্ট্রিং তুলনা কি ও (1)? অথবা স্ট্রিংয়ে অক্ষরের সংখ্যা বা মোট চর সংখ্যা? নাকি অন্য কিছু?
হাওয়ার্ড

1
@ ডুড, অবশ্যই এটা 4?
পিটার টেলর

উত্তর:


4

পাইথন

এখানে আমার সমাধান। আমি এখনও এটি ও (এন 2 ) হতে পারে বলে মনে করি , তবে আমার মনে হয় গড় কেসটি এর চেয়ে অনেক ভাল।

মূলত এটি প্রতিটি স্ট্রিংকে নরমাল করে কাজ করে যাতে কোনও ঘূর্ণন একই রকম হয়। উদাহরণ স্বরূপ:

'amazing' -> 'mazinga'
'mazinga' -> 'mazinga'
'azingam' -> 'mazinga'
'zingama' -> 'mazinga'
'ingamaz' -> 'mazinga'
'ngamazi' -> 'mazinga'
'gamazin' -> 'mazinga'

স্বাভাবিককরণ সর্বনিম্ন অক্ষর (চর কোড দ্বারা) অনুসন্ধান করে এবং স্ট্রিংটি ঘোরানোর মাধ্যমে করা হয় যাতে চরিত্রটি শেষ অবস্থানে থাকে। যদি সেই চরিত্রটি একাধিকবার ঘটে থাকে তবে প্রতিটি ঘটনার পরে অক্ষরগুলি ব্যবহৃত হয়। এটি প্রতিটি চক্রীয় শব্দকে একটি প্রচলিত উপস্থাপনা দেয় যা মানচিত্রে একটি কী হিসাবে ব্যবহার করা যেতে পারে।

স্বাভাবিককরণটি সবচেয়ে খারাপ ক্ষেত্রে এন 2 হয় (যেখানে স্ট্রিংয়ের প্রতিটি অক্ষর একই থাকে, যেমন aaaaaa) তবে বেশিরভাগ সময় কেবল কয়েকটি ঘটনা ঘটতে চলেছে এবং চলমান সময়টি আরও কাছাকাছি চলে আসবে n

আমার ল্যাপটপে (ডুয়াল কোর ইন্টেল অ্যাটম @ 1.66GHz এবং 1GB র্যাম), এটি চালানো /usr/share/dict/words(গড় 9.5 অক্ষরের দৈর্ঘ্য সহ 234,937 শব্দ) প্রায় 7.6 সেকেন্ড সময় নেয়।

#!/usr/bin/python

import sys

def normalize(string):
   # the minimum character in the string
   c = min(string) # O(n) operation
   indices = [] # here we will store all the indices where c occurs
   i = -1       # initialize the search index
   while True: # finding all indexes where c occurs is again O(n)
      i = string.find(c, i+1)
      if i == -1:
         break
      else:
         indices.append(i)
   if len(indices) == 1: # if it only occurs once, then we're done
      i = indices[0]
      return string[i:] + string[:i]
   else:
      i = map(lambda x:(x,x), indices)
      for _ in range(len(string)):                       # go over the whole string O(n)
         i = map(lambda x:((x[0]+1)%len(string), x[1]), i)  # increment the indexes that walk along  O(m)
         c = min(map(lambda x: string[x[0]], i))    # get min character from current indexes         O(m)
         i = filter(lambda x: string[x[0]] == c, i) # keep only the indexes that have that character O(m)
         # if there's only one index left after filtering, we're done
         if len(i) == 1:
            break
      # either there are multiple identical runs, or
      # we found the unique best run, in either case, we start the string from that
      # index
      i = i[0][0]
      return string[i:] + string[:i]

def main(filename):
   cyclic_words = set()
   with open(filename) as words:
      for word in words.readlines():
         cyclic_words.add(normalize(word[:-1])) # normalize without the trailing newline
   print len(cyclic_words)

if __name__ == '__main__':
   if len(sys.argv) > 1:
      main(sys.argv[1])
   else:
      main("/dev/stdin")

3

পাইথন (3) আবার

আমি যে পদ্ধতিটি ব্যবহার করেছি তা হ'ল স্ট্রিংয়ের প্রতিটি অক্ষর থেকে শুরু করে প্রতিটি শব্দের রোলিং হ্যাশ গণনা করা; যেহেতু এটি একটি ঘূর্ণায়মান হ্যাশ, এটি সমস্ত এন হ্যাশগুলি গণনা করতে O (n) (যেখানে n শব্দের দৈর্ঘ্য হয়) সময় নেয়। স্ট্রিংটিকে বেস -1114112 নম্বর হিসাবে গণ্য করা হয়, যা হ্যাশগুলি অনন্য বলে নিশ্চিত করে। (এটি হাস্কেল সমাধানের মতো, তবে এটি আরও কার্যকর যেহেতু এটি কেবল দু'বার স্ট্রিংয়ের মধ্য দিয়ে যায়))

তারপরে, প্রতিটি ইনপুট শব্দের জন্য, অ্যালগোরিদম এটি দেখতে পেল হ্যাশগুলির সেটটিতে ইতিমধ্যে (একটি পাইথন সেট, সুতরাং সেটটির আকারে ও (1)) আছে কিনা তা দেখতে এটির সর্বনিম্ন হ্যাশটি পরীক্ষা করে; যদি এটি হয় তবে শব্দ বা এর একটি ঘূর্ণন ইতিমধ্যে দেখা গেছে। অন্যথায়, এটি সেটে হ্যাশ যুক্ত করে।

কমান্ড-লাইন আর্গুমেন্টটি এমন কোনও ফাইলের নাম হওয়া উচিত যা প্রতি লাইনে একটি শব্দ থাকে (যেমন /usr/share/dict/words)।

import sys

def rollinghashes(string):
    base = 1114112
    curhash = 0
    for c in string:
        curhash = curhash * base + ord(c)
    yield curhash
    top = base ** len(string)
    for i in range(len(string) - 1):
        curhash = curhash * base % top + ord(string[i])
        yield curhash

def cycles(words, keepuniques=False):
    hashes = set()
    uniques = set()
    n = 0
    for word in words:
        h = min(rollinghashes(word))
        if h in hashes:
            continue
        else:
            n += 1
            if keepuniques:
                uniques.add(word)
            hashes.add(h)
    return n, uniques

if __name__ == "__main__":
    with open(sys.argv[1]) as words_file:
        print(cycles(line.strip() for line in words_file)[0])

1

Haskell,

এর দক্ষতা সম্পর্কে নিশ্চিত নয়, সম্ভবত সবচেয়ে খারাপ। ধারণাটি হ'ল প্রথমে সমস্ত শব্দের সমস্ত সম্ভাব্য ঘূর্ণন তৈরি করা, মানগুলি গণনা করুন যা স্ট্রিংগুলিকে স্বতন্ত্রভাবে উপস্থাপন করে এবং সর্বনিম্ন নির্বাচন করুন। এইভাবে আমরা একটি নম্বর পাই যা একটি চক্র গ্রুপের জন্য অনন্য।
আমরা এই নম্বর অনুসারে দলবদ্ধ করতে পারি এবং এই গোষ্ঠীর সংখ্যাটি পরীক্ষা করতে পারি।

যদি এন তালিকার শব্দের সংখ্যা হয় এবং মি একটি শব্দের দৈর্ঘ্য হয় তবে সমস্ত শব্দের জন্য 'চক্রীয় গ্রুপ সংখ্যা' গণনা করা O(n*m)বাছাই করা O(n log n)এবং গোষ্ঠীকরণ করা O(n)

import Data.List
import Data.Char
import Data.Ord
import Data.Function

groupUnsortedOn f = groupBy ((==) `on` f) . sortBy(compare `on` f)
allCycles w = init $ zipWith (++) (tails w)(inits w)
wordval = foldl (\a b -> a*256 + (fromIntegral $ ord b)) 0
uniqcycle = minimumBy (comparing wordval) . allCycles
cyclicGroupCount = length . groupUnsortedOn uniqcycle

1

ম্যাথামেটিকাল

আবার শুরু করার সিদ্ধান্ত নিয়েছে, এখন আমি খেলার নিয়মগুলি বুঝতে পারি (আমার মনে হয়)।

দৈর্ঘ্যের অনন্য এলোমেলোভাবে রচিত "শব্দ" (কেবলমাত্র নিম্ন কেস) এর একটি 10000 শব্দের অভিধান similar

ClearAll[dictionary]      
dictionary[chars_,nWords_]:=DeleteDuplicates[Table[FromCharacterCode@RandomInteger[{97,122},
chars],{nWords}]];
n=16000;
d3=Take[dictionary[3,n],10^4];
d4=Take[dictionary[4,n],10^4];
d5=Take[dictionary[5,n],10^4];
d6=Take[dictionary[6,n],10^4];
d7=Take[dictionary[7,n],10^4];
d8=Take[dictionary[8,n],10^4];

gঅভিধানের বর্তমান সংস্করণটি পরীক্ষা করে নেয়। শীর্ষ শব্দটি চক্রীয় রূপগুলির সাথে যুক্ত হয়েছে (যদি কোনও উপস্থিত থাকে)। শব্দটি এবং এর মিলগুলি outপ্রক্রিয়াজাত শব্দের আউটপুট তালিকায় যুক্ত হয় । শব্দটি অভিধান থেকে সরানো হয়েছে are

g[{wds_,out_}] := 
   If[wds=={},{wds,out},
   Module[{s=wds[[1]],t,c},
   t=Table[StringRotateLeft[s, k], {k, StringLength[s]}];
   c=Intersection[wds,t];
   {Complement[wds,t],Append[out,c]}]]

f সমস্ত শব্দ অভিধানে চলমান।

f[dict_]:=FixedPoint[g,{dict,{}}][[2]]

উদাহরণ 1 : প্রকৃত শব্দ

r = f[{"teaks", "words", "spot", "pots", "sword", "steak", "hand"}]
Length[r]

ste ste "স্টেক", "টিগস"}, hand "হাত"}, {"হাঁড়ি", "স্পট"}, sword "তরোয়াল", "শব্দ"}}
4


উদাহরণ 2 : কৃত্রিম শব্দ। দৈর্ঘ্যের স্ট্রিং এর অভিধান 3. প্রথম, সময়। তারপরে চক্র শব্দের সংখ্যা।

f[d3]//AbsoluteTiming
Length[%[[2]]]

D3

5402


শব্দ দৈর্ঘ্যের একটি ফাংশন হিসাবে সময় । প্রতিটি অভিধানে 10000 শব্দ

সময়

ও এর পরিপ্রেক্ষিতে কীভাবে ফলাফলগুলি ব্যাখ্যা করতে হয় তা আমি বিশেষত জানি না simple সরল ভাষায়, সময়টি তিনটি অক্ষর অভিধান থেকে চারটি অক্ষরের অভিধানে প্রায় দ্বিগুণ হয়। সময়টি প্রায় অবহেলিতভাবে 4 থেকে 8 টি অক্ষর পর্যন্ত বৃদ্ধি পায়।


আপনি যে অভিধানটি ব্যবহার করেছেন তা কি আপনি সম্ভবত একটি লিঙ্ক পোস্ট করতে পারেন যাতে আমি আপনার সাথে তুলনা করতে পারি?
উদ্বিগ্নগণ

অভিধান. txt এর নিম্নলিখিত লিঙ্কটিতে কাজ করা উচিত: bitshare.com/files/oy62qgro/d অভিধান. txt.html (ডাউনলোড শুরু হওয়ার জন্য আপনাকে যে মিনিটের জন্য অপেক্ষা করতে হবে তার জন্য দুঃখিত।) বিটিডাব্লু, ফাইলটিতে 3char, 4char রয়েছে ... 8চার চারটি অভিধানে সব একসাথে, প্রতিটিতে 10000 শব্দ। আপনি তাদের আলাদা করতে চাইবেন।
ডেভিডসি

অসাধারণ. অনেক অনেক ধন্যবাদ :)
এগলোন্লেগস

1

চতুর্ভুজ সময় এড়িয়ে ও (এন) এ এটি করা যেতে পারে। ধারণাটি হ'ল দুটি বার বেস স্ট্রিংকে অনুসরণ করে পুরো বৃত্তটি তৈরি করা। সুতরাং আমরা "আশ্চর্যজনক" এর সাথে সম্পর্কিত সমস্ত চক্রীয় স্ট্রিং চেক করতে পুরো চক্র স্ট্রিং হিসাবে "আশ্চর্যজনক" তৈরি করি।

নীচে জাভা সমাধান:

public static void main(String[] args){
    //args[0] is the base string and following strings are assumed to be
    //cyclic strings to check 
    int arrLen = args.length;
    int cyclicWordCount = 0;
    if(arrLen<1){
        System.out.println("Invalid usage. Supply argument strings...");
        return;
    }else if(arrLen==1){
        System.out.println("Cyclic word count=0");
        return;         
    }//if

    String baseString = args[0];
    StringBuilder sb = new StringBuilder();
    // Traverse base string twice appending characters
    // Eg: construct 'amazingamazin' from 'amazing'
    for(int i=0;i<2*baseString.length()-1;i++)
        sb.append(args[0].charAt(i%baseString.length()));

    // All cyclic strings are now in the 'full circle' string
    String fullCircle = sb.toString();
    System.out.println("Constructed string= "+fullCircle);

    for(int i=1;i<arrLen;i++)
    //Do a length check in addition to contains
     if(baseString.length()==args[i].length()&&fullCircle.contains(args[i])){
        System.out.println("Found cyclic word: "+args[i]);
        cyclicWordCount++;
    }

    System.out.println("Cyclic word count= "+cyclicWordCount);
}//main

0

আমি জানি না এটি খুব দক্ষ কিনা, তবে এটি আমার প্রথম ক্র্যাক।

private static int countCyclicWords(String[] input) {
    HashSet<String> hashSet = new HashSet<String>();
    String permutation;
    int count = 0;

    for (String s : input) {
        if (hashSet.contains(s)) {
            continue;
        } else {
            count++;
            for (int i = 0; i < s.length(); i++) {
                permutation = s.substring(1) + s.substring(0, 1);
                s = permutation;
                hashSet.add(s);
            }
        }
    }

    return count;
}

0

পার্ল

নিশ্চিত না যে আমি সমস্যাটি বুঝতে পেরেছি, তবে এটি কমপক্ষে মন্তব্যে পোস্ট করা ডডের সাথে মিলছে। আমার অবশ্যই ভুল বিশ্লেষণ সংশোধন করুন।

স্ট্রিং তালিকার প্রদত্ত এন শব্দের প্রতিটি শব্দের জন্য আপনাকে সবচেয়ে খারাপ ক্ষেত্রে ডাব্লু এর সমস্ত অক্ষরের মধ্য দিয়ে যেতে হবে। আমাকে ধরে নিতে হবে হ্যাশ অপারেশনগুলি ধ্রুব সময়ে করা হয়।

use strict;
use warnings;

my @words = ( "teaks", "words", "spot", "pots", "sword", "steak", "hand" );

sub count
{
  my %h = ();

  foreach my $w (@_)
  {
    my $n = length($w);

    # concatenate the word with itself. then all substrings the
    # same length as word are rotations of word.
    my $s = $w . $w;

    # examine each rotation of word. add word to the hash if
    # no rotation already exists in the hash
    $h{$w} = undef unless
      grep { exists $h{substr $s, $_, $n} } 0 .. $n - 1;
  }

  return keys %h;
}

print scalar count(@words), $/;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.