মার্সেল প্রাউস্ট এবং মার্কোভ ডিফিকার সিকিউরিটি সার্ভিসের টি 9 পাঠ্য


11

যেন এই চ্যালেঞ্জটি স্পিরিটে আরও পাইথোনস্ক হতে পারে ... মার্কভ চেইন বা এনক্রিপশন কৌশলগুলির পূর্বে কোনও জ্ঞানের প্রয়োজন নেই।

আপনি একজন গুপ্তচর, যাকে ব্রিটিশ সুরক্ষা পরিষেবা এম 1 এস থেকে কিছু গুরুত্বপূর্ণ তথ্য নেওয়া দরকার। এম 1 এস এর এজেন্টরা ভাল জানেন যে তাদের ওয়াই-ফাই সংকেতগুলি আটকানো যেতে পারে, তাদের অ্যান্ড্রয়েড / আইওএস সুরক্ষা দুর্বলতাগুলি ইত্যাদি ব্যবহার করা যেতে পারে, তাই তারা সকলেই নোকিয়া 3310 টি পাঠ্য তথ্য প্রেরণ করতে ব্যবহার করছেন যা টি 9 স্বতঃসমাপ্তি ব্যবহার করে টাইপ করা হয় ।

আপনি পূর্বে গোয়েন্দা সংস্থাকে সরবরাহ করার জন্য ফোনগুলি হ্যাক করে দিয়েছিলেন এবং তাদের দুর্দান্ত প্লাস্টিকের কীবোর্ডের অধীনে কীলগারগুলি ইনস্টল করেছিলেন, সুতরাং এখন আপনি তাদের টাইপ করা চিঠির সাথে সংখ্যার ক্রমগুলি পেয়েছেন, সুতরাং " agগল এজেন্টদের বাসা থেকে সতর্কতা ছেড়ে দিয়েছে " হয়ে যায় "

84303245304270533808430637802537808430243687

কিন্তু অপেক্ষা করো! কিছু টি 9 সিকোয়েন্সগুলি অস্পষ্ট ("6263" "নাম", "মাণে" বা "ওও" হতে পারে; যতই অস্পষ্ট, ততই সন্দেহজনক হয়ে ওঠে!), তাহলে আপনি কী করবেন? আপনি জানেন যে এম 1 এস ব্যবহার করে একমাত্র প্রবেশিকা পরীক্ষাটি 15 সেকেন্ডে মার্সেল প্রাউস্টের মাস্টারপিস "রিমেন্ডার অব থিংস অব থিংস" এর সংক্ষিপ্তসার করছে, সুতরাং আপনি পুরো শেফ-ডি'এর ফ্রিকোয়েন্সি বিতরণ অনুযায়ী পূর্ববর্তীটির পরে যে শব্দটি আসে তা বেছে নিতে চান গর্বিত!

আপনি কোডটি ক্র্যাক করতে পারেন এবং মূল বার্তাটি কী হতে পারে তা পেতে পারেন?

টি 9 এর নীতি

এজেন্টরা ব্যবহৃত নোকিয়া 3310 কীবোর্ড

টি 9 স্বতঃসমাপ্তি প্রক্রিয়াটি নীচে বর্ণিত হতে পারে। এটি উপরের ছবিতে প্রদর্শিত বর্ণ অনুসারে বর্ণমালার অক্ষরগুলিকে মানচিত্র করে।

abc     -> 2
def     -> 3
ghi     -> 4
jkl     -> 5
mno     -> 6
pqrs    -> 7
tuv     -> 8
wxyz    -> 9
<space> -> 0
<other> -> <is deleted>

টি 9 ডিক্রিপ্টর অঙ্কগুলির ক্রম পেয়েছে এবং সেই শব্দটি কী টাইপ করতে পারে তা অনুমান করার চেষ্টা করে। এটি একটি স্ট্যান্ডার্ড ফ্রিকোয়েন্সি টেবিল ব্যবহার করতে পারে তবে আমরা আরও এক ধাপ এগিয়ে চলেছি এবং একটি মার্কভ চেইন ব্যবহার করে পরবর্তী শব্দটির পূর্বাভাস দিচ্ছি!

নমুনা শেখা

কর্পাস হয় প্রুস্তের এর "থিংস অতীত স্মরণ" এর এই প্রচন্ডভাবে ছিনতাই সংস্করণ ( s/-/ /g, s/['’]s //gএবং s/[^a-zA-Z ]//g- তফাৎ যাও বিভ্রান্তিকর সম্বন্ধসূচক 's!) মূলত প্রকাশিত বিশ্ববিদ্যালয়ের অ্যাডিলেড ওয়েবসাইট (এই কাজের টেক্সট অস্ট্রেলিয়ায় সার্বজনিক ডোমেনে আছে)।

পুরো পাঠ্যটিকে একটি স্ট্রিং হিসাবে, একটি দীর্ঘ বাক্য হিসাবে, দীর্ঘ লম্বা শব্দের (যেটি আপনার ভাষার পক্ষে আরও সুবিধাজনক) হিসাবে বিশ্লেষণ করা উচিত , লাইনব্রেকগুলি ছিনিয়ে নেওয়া এবং ফাঁকা জায়গায় শব্দের মধ্যে বিভক্ত করা উচিত । (আমি একটি একক অনুচ্ছেদে ফাইল সরবরাহ করি না কারণ এগুলি গিথুব সরঞ্জামগুলির দ্বারা নষ্ট হয়ে যেতে পারে))

আমি কীভাবে পুরো পাঠটিকে এক স্ট্রিং / বাক্য হিসাবে পড়ব? আর এর একটি উদাহরণ :

p_raw  <- read.table("proust.txt", sep="\t") # Because there are no tabs
p_vec  <- as.character(p_raw$V1)       # Conversion to character vector
p_str  <- paste(p_vec, collapse=" ")   # One long string with spaces
p_spl  <- strsplit(p_str, split=" ")[[1]] # Vector of 1360883 words
proust <- p_spl[p_spl!=""]           # Remove empty entries — 1360797

কার্য

একটি সংখ্যা হিসাবে অঙ্কের ক্রম দেওয়া, একটি দীর্ঘ বাক্য হিসাবে বিবেচিত এই প্রশিক্ষণ পাঠ্যের উপর ভিত্তি করে পরবর্তী শব্দ এক্স অনুমান করতে একটি সম্ভাব্য পাঠ্য স্ট্রিংটি যুক্ত T9 কী ব্যবহার করে একটি সম্ভাব্য শৃঙ্খলা ব্যবহার করে টাইপ করা যায় return

তাহলে এক্স পাঠের প্রথম T9 শব্দ এবং একাধিক অনুমান, আছে, এলোমেলোভাবে একটি চয়ন অন্যথায় শুধুমাত্র একটি সম্ভাব্য বাছাই।

সমস্ত পরবর্তী T9- শব্দের জন্য এক্স (i) এর আগে ডিক্রিফারড ডাব্লু (i-1) শব্দের আগে :

  1. একটি T9 শব্দ যদি এক্স মধ্যে একটি স্বাভাবিক শব্দ পরিবর্তিত করা যায় এক্স এক অনন্য উপায়, এটা না।
  2. যদি এক্সের জন্য একাধিক রূপান্তর বিকল্প উপলব্ধ থাকে তবে এক্স 1 , এক্স 2 , ... বলুন , পূর্ববর্তী অনুমানিত শব্দটি ডাব্লু দেখুন
    • যদি ডাব্লু কখনই প্রাউস্টের মূল কাজটিতে এক্সে ম্যাপ করে এমন কিছু অনুসরণ না করে , সম্ভাব্য এক্স 1, এক্স 2, ... এলোমেলোভাবে বেছে নিন।
    • তাহলে W X সবসময় অনুরূপ W X1 মূল এবং কোন সমবর্তী আছে একাদশ খামকা মধ্যে ম্যাপ করা যেতে পারে এক্স , বাছাই X1
    • তাহলে W X রূপান্তরিত করা যেতে পারে W X1 , W x2 , ... যে কর্পাস খুঁজে পাওয়া যেতে পারে, তবে সব সম্ভব গণনা একাদশ 'যে ফলো গুলি W এবং ম্যাপ এক্স কর্পাস এবং বাছাই একাদশ সম্ভাব্যতা সঙ্গে একাদশ / (X1 + x2 + ...)

উদাহরণ 2a। যদি বার্তাটি থাকে তবে 76630489কোথায় 489হতে পারে guyবা ivy(তারা কমপক্ষে একবার কর্পাসে উপস্থিত হবে), (খুব সম্ভবত প্রথম শব্দ) 7663হিসাবে ডিক্রিফার করা যেতে পারে some। যদি কর্পাসে someমানচিত্রের কোনও কিছু অনুসরণ 489না করে থাকে তবে সম্ভাব্যতা 0.5 দিয়ে বাছুন guyবা ivyএলোমেলোভাবে।

উদাহরণ 2 বি। যদি বার্তাটি থাকে তবে 766302277437কোথায় বা 2277437হতে পারে , ততই ডিক্রিফার করা যেতে পারে । যদি প্রাউস্ট সর্বদা ব্যবহৃত হয় এবং কখনই না হয় তবে বেছে নিন ।barriercarrier7663somesome carriersome barriersome carrier

উদাহরণ 2 সি। মনে করুন আপনি ক্রমটি ডিসাইফার করতে চান 5363076635363যেমন পূর্বাভাস ছিল lend7663এর মধ্যে যে কোনো হতে পারে: pond, roofএবং some। আপনি lendনমুনা কর্পাসে নিম্নলিখিত শব্দটির উপস্থিতি গণনা করুন । মনে করুন আপনি এরকম কিছু পেয়েছেন (কেবল উদাহরণস্বরূপ):

        T9  Word following lend  Occurrences
      7663  some                           7
      7663  pond                           2
      7663  roof                           1

সুতরাং যদি 7663এর আগে হয় lend, 7/(7+2+1)=70%সম্ভাবনা রয়েছে যা 20% এবং 10% এর 7663জন্য দাঁড়িয়েছে । আপনার অ্যালগরিদম 70% ক্ষেত্রে, 20% ক্ষেত্রে ইত্যাদিতে উত্পন্ন করা উচিত etc.somepondrooflend somelend pond

আপনি নিরাপদে ধরে নিতে পারেন যে এজেন্টরা কেবল এজে অক্ষর এবং স্পেস ব্যবহার করে (কোনও বিরাম চিহ্ন, কোনও অধিকার নেই 's, এবং কোনও সংখ্যা নেই)।

আপনি এটিও ধরে নিতে পারেন যে এম 1 এস এর এজেন্টরা কখনই "রিমেনার অব থিংস পাস্ট" (যেটি 29,237 শব্দের সম্পূর্ণ শব্দভাণ্ডার!) এর বাইরে কোনও শব্দ ব্যবহার করে না

এই চ্যালেঞ্জটিতে টি 9 ফোক্যালারিটি কার্যকর করা হয়েছিল , সুতরাং আপনার এটির দিকে নজর দেওয়া যেতে পারে।

আপনি যদি কোনো সাহায্যের প্রয়োজন হয়, তাহলে সম্ভাব্য চেইন মহান মধ্যে আয়ত্ত করা হয়েছিল এই , যে এবং নিম্নলিখিত চ্যালেঞ্জ, কিন্তু আপনি এমন ধরনের চেইন নীতিকে জানা প্রয়োজন না: সবকিছু টাস্ক বিবৃত করা হয়।

পরীক্ষার মামলা

--Inputs--
20784250276960369
20784250276960369
84303245304270533808430637802537808430243687
94280343084306289072908608430262780482737
94280343084306289072908608430262780482737

--Possible outputs--
c quick brown fox
a stick crown fox
the eagle gas left the nest blest vie agents
what did the navy pay to the coast guards
what did the navy raz un the coast guards

নিয়মাবলী:

  • স্ট্যান্ডার্ড লুফোলস প্রযোজ্য।
  • আপনি আসল বার্তাটি জানেন না, আপনি যা পেয়েছেন তা হ'ল অঙ্কগুলির ক্রম এবং proust.txt ফাইল যা আপনার কেবল মেমরি / ওয়ার্কস্পেস / যা কিছুতেই লোড করতে হবে। স্বাবলম্বী কিছু থাকার দরকার নেই; ধরে proust.txtনেওয়া সর্বদা অ্যাক্সেসযোগ্য।
  • একাধিক ডিক্রিপশন বিকল্প কর্পাস অনুসারে সম্ভাব্য হলে আপনার অ্যালগরিদম অবশ্যই সম্পর্কিত সম্ভাব্যতার সাথে বিভিন্ন আউটপুট উত্পাদন করতে সক্ষম হবে (উদাহরণ 2 সি দেখুন)।

আপনার যথাসম্ভব বিচক্ষণ থাকা দরকার, তাই সংক্ষিপ্ততম কোডটি জয়ী হয়!

PS এই সম্ভাব্যতা সংক্রান্ত অ্যালগরিদমের সুস্পষ্ট সুবিধা হ'ল এই বিষয়টি যে আপনি একটি দ্ব্যর্থহীন deciphered স্ট্রিংয়ের জন্য সত্যিকারের আসল স্ট্রিংটি পাবেন তবে অপেক্ষা করুন ...

আংশিক মিলের দ্বারা পিপিএস ভবিষ্যদ্বাণীও দেখুন ।


স্যান্ডবক্স থেকে পিটার টেলরের মন্তব্যগুলি আমলে নেওয়া হয়েছিল। দুঃখের বিষয়, একাধিক আপডেট সত্ত্বেও এটি পোস্ট করা সপ্তাহের মধ্যে খুব কম লোক প্রতিক্রিয়া জানিয়েছিল, তাই কোনও পরামর্শ স্বাগত! বিটিডব্লিউ, এটি আমার প্রথম চ্যালেঞ্জ!
Andreï Kostyrka

আমার সন্দেহ হয় যে আপনি অনেক প্রতিক্রিয়া না পেয়েছেন তার একটি বড় কারণ এই সমস্যাটি বোঝার জন্য প্রয়োজনীয় উন্নত জ্ঞান। আপনি যদি হয় একটি বৃহত্তর ভিড় আপীল এই চ্যালেঞ্জ অনুপস্থিত, আমি কিছু আগে উদাহরণ যে কর্মক্ষেত্রে :) মার্কভ চেইন দেন সহ বলতে চাই
নাথন মেরিল

@ নাথানমারিল ঠিক আছে, আমি নমুনা চ্যালেঞ্জগুলিতে 3 টি লিঙ্ক যুক্ত করেছি। তবে কোনও ব্যবহারকারীর মার্কোভ চেইনগুলি একেবারেই জানার দরকার নেই কারণ প্রশ্ন বডিটিতে কার্যটি আলগোরিদিমিকভাবে যতটা সম্ভব বর্ণনা করা হয়েছে: যদি এক্স হয় তবে এই শেখার নমুনায় জেড গণনা করে প্রাপ্ত সম্ভাবনার সাথে ওয়াই করুন। আমি এটিকে যতটা স্বয়ংসম্পূর্ণ করার চেষ্টা করেছি ...
Andreï Kostyrka

ওহ, আমি বুঝেছি. আপনি যদি এটি ব্যাখ্যা না করেন, আমি এটি বন্ধ করার পক্ষে ভোট দিতাম। এটা ঠিক দেখায় মত উন্নত জ্ঞান দরকার :)
নাথন মেরিল

1
আমি এই চ্যালেঞ্জটি পছন্দ করি, তবে আমার কাছে বসে বসে কোনও গল্ফ তৈরি করতে / গল্ফ তৈরি করার মতো সময় এখনও পাইনি। আশা করি শিগগিরই তা ঘটবে।
মেগো

উত্তর:


1

আর সমাধান, কী করা যায় তার প্রতিদ্বন্দ্বী চিত্রণ

প্রথমত, আমরা শব্দের ক্রম মেমোরিতে লোড করি:

p_raw  <- read.table("proust.txt", sep="\t") # Because there are no tabs
p_vec  <- as.character(p_raw$V1)       # Conversion to character vector
p_str  <- paste(p_vec, collapse=" ")   # One long string with spaces
p_spl  <- strsplit(p_str, split=" ")[[1]] # Vector of 1360883 words
proust <- p_spl[p_spl!=""]           # Remove empty entries — 1360797

দ্বিতীয়ত, আমাদের একটি ফাংশন প্রয়োজন যা কোনও পাঠ্য টি-আইফিস:

t9 <- function (x) {
  x <- chartr(paste(c(letters, " "), collapse=""), "222333444555666777788899990", tolower(x))
  x <- gsub("[^0-9]", "", x, perl = TRUE) # Safety check
  x <- x[x!=""] # Also for safety because... you know...
  x
}

তারপরে, আমরা টি 9-ইফাই গর্বিত:

p9 <- t9(proust)

চূড়ান্ত প্রস্তুতি: আমরা কল করি এমন একটি ফাংশন ব্যবহার করে আমরা জিরোতে ইনপুট স্ট্রিংটি বিভক্ত করি prep:

prep <- function (x) {
  x <- chartr("0", " ", x)
  x <- strsplit(x, " ")[[1]]
  x <- x[x!=""] # Boil the empty strings for safety
  x
}

এবং এখন আমি এমন একটি ফাংশন প্রস্তাব করছি যা সংখ্যার যে কোনও ইনপুট স্ট্রিং নেয়, prepসেগুলি এবং শব্দগুলি একে একে ডিক্রিফার করে:

decip <- function(x, verbose = FALSE) {
  x <- prep(x)
  l <- length(x)
  decrypted <- rep(NA, l)
  tb <- table(proust[which(p9 == x[1])])
  decrypted[1] <- sample(names(tb), 1, prob=tb/sum(tb))
  if (verbose) print(decrypted[1])
  for (i in 2:l) {
    mtchl <- p9 == x[i]
    mtch <- which(mtchl)  # Positions that matched
    pmtch <- proust[mtch] # Words that matched
    tb <- table(pmtch)    # Count occurrences that matched
    if (length(tb)==1) {  # It is either 1 or >1
      decrypted[i] <- names(tb)[1]
      if (verbose) print(paste0("i = ", i, ", case 1: unique decryption"))
      } else {  # If there are more than one ways to decipher...
      preced <- proust[mtch-1] 
      s <- sum(preced==decrypted[i-1])
      if (s==0) {
        decrypted[i] <- sample(names(tb), 1)
        if (verbose) print(paste0("i = ", i, ", case 2a: multiple decryption, collocation never used, picking at random"))
        } else {
        tb2 <- table(pmtch[preced==decrypted[i-1]])
        if (length(tb2)==1) {
          decrypted[i] <-  names(tb2)[1]
          if (verbose) print(paste0("i = ", i, ", case 2b: multiple decryption, only one collocation found, using it"))
        } else {
          decrypted[i] <- sample(names(tb2), 1, prob = tb2/sum(tb2))
          if (verbose) print(paste0("i = ", i, ", case 2c: multiple decryption, ", length(tb2), " choices"))
          }
      }
    }
    if(verbose) print(decrypted[i])
  }
  decrypted
}

এবং এখন এটি আসলে কী করছে:

decip("20784250276960369", verbose=TRUE)
----
[1] "a"
[1] "i = 2, case 2c: multiple decryption, 2 choices"
[1] "quick"
[1] "i = 3, case 2a: multiple decryption, collocation never used, picking at random"
[1] "brown"
[1] "i = 4, case 1: unique decryption"
[1] "fox"
[1] "a"     "quick" "brown" "fox" 

দ্বিতীয় উদাহরণ:

decip("84303245304270533808430637802537808430243687", verbose=TRUE)
----
[1] "what"
[1] "i = 2, case 2b: multiple decryption, only one collocation found, using it"
[1] "did"
[1] "i = 3, case 2b: multiple decryption, only one collocation found, using it"
[1] "the"
[1] "i = 4, case 1: unique decryption"
[1] "navy"
[1] "i = 5, case 2a: multiple decryption, collocation never used, picking at random"
[1] "raz"
[1] "i = 6, case 2a: multiple decryption, collocation never used, picking at random"
[1] "um"
[1] "i = 7, case 2a: multiple decryption, collocation never used, picking at random"
[1] "the"
[1] "i = 8, case 2b: multiple decryption, only one collocation found, using it"
[1] "coast"
[1] "i = 9, case 1: unique decryption"
[1] "guards"
[1] "what"   "did"    "the"    "navy"   "raz"    "um"     "the"    "coast"  "guards"

এটি গল্ফ করা যেতে পারে যে মন্তব্য করবেন না। দেখে মনে হচ্ছে যে আমার ভয়ানক ভার্বোসটির কারণে খুব কম লোকই এই চ্যালেঞ্জের প্রতি আগ্রহী, তাই কোনও সম্ভাব্য প্রোগ্রামটি কেমন হতে পারে তা দেখানোর জন্য আমি এই উত্তরটি পোস্ট করেছি। আপনার এই উত্তরটি আপভোট / ডাউনভোট করার দরকার নেই।


1

পাইথন 3, 316 বাইট

from random import*
from collections import*
def d(s,f):
 D=defaultdict(Counter);p=q=''
 for w in open(f).read().split():D[w.translate({97+c:(c-(c>17)-(c>24))//3+50for c in range(26)})].update([w]);D[p].update([w]);p=w
 for c in s.split('0'):q=choice([*(len(D[c])>1and D[c]&D[q]or D[c]).elements()]);print(q,end=' ')
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.