【演算法】用c#實現自定義字元串編碼及圍欄解碼方法

来源:https://www.cnblogs.com/lan80/archive/2023/08/21/17645151.html
-Advertisement-
Play Games

先決條件 Visual Studio 2019 v16.9 預覽版1或更高版本(通過WSL可選組件進行.NET調試)。若要檢查 WSL 組件,請選擇 “工具” > “獲取工具和功能” 。 在 Visual Studio 安裝程式中,選擇 “單個組件”,然後鍵入 “WSL” 搜索安裝組件 。 安裝WS ...


編寫一個函數/方法,它接受2個參數、一個字元串和軌道數,並返回ENCODED字元串。

編寫第二個函數/方法,它接受2個參數、一個編碼字元串和軌道數,並返回DECODED字元串。

然後使用圍欄密碼對其進行解碼。

這種密碼用於通過將每個字元沿著一組“豎狀軌道”依次放在對角線上來對字元串進行編碼。首先開始對角向下移動。當你到達底部時,反轉方向,對角向上移動,直到你到達頂部軌道。繼續,直到到達字元串的末尾。然後從左到右讀取每個“尾號”以導出編碼字元串。

例如,字元串“WEAREDISCOVEREDFLEATONCE”可以在三軌系統中表示如下:
W E C R L T E

E R D S O E E F E A O C

A I V D E N

編碼的字元串將是:
WECRLTEERDSOEEFEAOCAIVDEN

對於編碼和解碼,假設尾號的數量>=2,並且傳遞空字元串將返回空字元串。

請註意,為了簡單起見,上面的示例排除了標點符號和空格。然而,也有一些測試包括標點符號。不要過濾掉標點符號,因為它們是字元串的一部分。


演算法實現:

 1 using System;
 2 using System.Linq;
 3 
 4 public class RailFenceCipher
 5 {
 6    public static string Encode(string s, int n)
 7    {
 8        var mod = (n - 1) * 2;
 9        return string.Concat(s.Select((c, i) => new { c, i })
10           .OrderBy(a => Math.Min(a.i % mod, mod - a.i % mod))
11           .Select(a => a.c));
12    }
13 
14    public static string Decode(string s, int n)
15    {
16        var mod = (n - 1) * 2;
17        var pattern = Enumerable.Range(0, s.Length)
18           .OrderBy(i => Math.Min(i % mod, mod - i % mod));
19        return string.Concat(s.Zip(pattern, (c, i) => new { c, i })
20           .OrderBy(a => a.i).Select(a => a.c));
21    }
22 }

測試用例:

  1 using NUnit.Framework;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.Linq;
  5 public class SolutionTest
  6 {
  7     [Test]
  8     public void BasicTests()
  9     {
 10         string[][] config =
 11         {
 12             new[] { "Hello, World!", "Hoo!el,Wrdl l" },               // encode
 13             new[] { "Hello, World!", "Hlo ol!el,Wrd" },               // encode
 14             new[] { "Hello, World!", "H !e,Wdloollr" },               // encode
 15             new[] { "H !e,Wdloollr", "Hello, World!" },               //  decode
 16             new[] { "", "" },                            // encode
 17             new[] { "", "" },                            //  decode
 18             new[] { "WEAREDISCOVEREDFLEEATONCE", "WECRLTEERDSOEEFEAOCAIVDEN" },   // encode
 19             new[] { "WECRLTEERDSOEEFEAOCAIVDEN", "WEAREDISCOVEREDFLEEATONCE" },   //  decode
 20             new[] { "WEAREDISCOVEREDFLEEATONCE", "WIREEEDSEEEACAECVDLTNROFO" },   // encode
 21             new[] { "WIREEEDSEEEACAECVDLTNROFO", "WEAREDISCOVEREDFLEEATONCE" },   //  decode
 22             new[] { "WEAREDISCOVEREDFLEEATONCE", "WCLEESOFECAIVDENRDEEAOERT" },   // encode
 23             new[] { "WECRLTEERDSOEEFEAOCAIVDEN", "WLSADOOTEEECEAEECRFINVEDR" }    //  decode
 24         };
 25         int[] rails = { 3, 2, 4, 4, 3, 3, 3, 3, 4, 4, 5, 5 };
 26         for (int i = 0; i < config.Length; i++)
 27         {
 28             var actual = i % 2 == 0 || i == 1
 29                 ? RailFenceCipher.Encode(config[i][0], rails[i])
 30                 : RailFenceCipher.Decode(config[i][0], rails[i]);
 31 
 32             Assert.AreEqual(config[i][1], actual);
 33         }
 34     }
 35 
 36     /* *****************
 37      *   RANDOM TESTS
 38      * *****************/
 39 
 40     private class Sol
 41     {
 42         private static IEnumerable<T> Fencer<T>(int n, IEnumerable<T> str)
 43         {
 44             var rails = Enumerable.Range(0, n).Select(r => new List<T>()).ToList();
 45             int[] data = { 0, 1 };
 46             int x = 0, dx = 1;
 47             foreach (var t in str)
 48             {
 49                 rails[data[x]].Add(t);
 50                 if (data[x] == n - 1 && data[dx] > 0 || data[x] == 0 && data[dx] < 0)
 51                     data[dx] *= -1;
 52                 data[x] += data[dx];
 53             }
 54             return rails.SelectMany(lst => lst);
 55         }
 56 
 57         public static string Encode(string s, int n) => new string(Fencer(n, s).ToArray());
 58 
 59         public static string Decode(string s, int n)
 60         {
 61             char[] arr = new char[s.Length];
 62             int[] j = { 0 };
 63             Fencer(n, Enumerable.Range(0, s.Length)).ToList().ForEach(i => arr[i] = s[j[0]++]);
 64             return new string(arr);
 65         }
 66     }
 67 
 68     private Random rnd = new Random();
 69 
 70     private int Rand(int start, int end) { return start + rnd.Next(end - start); }
 71 
 72     [Test]
 73     public void FixedStringVariousRails()
 74     {
 75         var msg = "WEAREDISCOVEREDFLEEATONCE";
 76         Console.WriteLine($"Input for these tests:\n{msg}");
 77 
 78         for (int r = 0; r < 10; r++)
 79         {
 80             var rails = Rand(2, 11);
 81             var exp = Sol.Encode(msg, rails);
 82             Assert.AreEqual(exp, RailFenceCipher.Encode(msg, rails));
 83 
 84             rails = Rand(2, 11);
 85             exp = Sol.Decode(msg, rails);
 86             Assert.AreEqual(exp, RailFenceCipher.Decode(msg, rails));
 87         }
 88     }
 89 
 90     private static string lorem = "Amet non facere minima iure unde, provident, "
 91                                   + "veritatis officiis asperiores ipsa eveniet sit! Deserunt "
 92                                   + "autem excepturi quibusdam iure unde! Porro alias distinctio "
 93                                   + "ipsam iure exercitationem molestiae. Voluptate fugiat quasi maiores!jk";
 94     private static List<string> lorarr = lorem.Split(' ').ToList();
 95 
 96     [Test]
 97     public void RandomTests()
 98     {
 99         Console.WriteLine($"Base string for these tests (or a shuffled version):\n{lorem}");
100 
101         for (int r = 0; r < 50; r++)
102         {
103             var msg = Shuffle();
104             int rails = Rand(2, 51);
105             var exp = Sol.Encode(msg, rails);
106             Assert.AreEqual(exp, RailFenceCipher.Encode(msg, rails));
107 
108             msg = Shuffle();
109             rails = Rand(2, 51);
110             exp = Sol.Decode(msg, rails);
111             Assert.AreEqual(exp, RailFenceCipher.Decode(msg, rails));
112         }
113     }
114 
115     private string Shuffle()
116     {
117         Shuffle(lorarr);
118         return string.Join(" ", lorarr);
119     }
120 
121     public static void Shuffle<T>(List<T> deck)
122     {
123         var rnd = new Random();
124         for (int n = deck.Count - 1; n > 0; --n)
125         {
126             int k = rnd.Next(n + 1);
127             T temp = deck[n];
128             deck[n] = deck[k];
129             deck[k] = temp;
130         }
131     }
132 }

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 根節點枚舉的過程要做到高效並非一件容易的事情,現在Java應用越做越龐大,如果你是JVM的開發者,你會怎麼去做? ...
  • `gosec` 是一個用於在 Go 代碼中查找安全問題的開源工具,它可以幫助發現可能的漏洞和潛在的安全風險。以下是關於 `gosec` 的詳細介紹: ## 1. 工具概述: `gosec` 是一個靜態分析工具,用於掃描 Go 代碼以查找潛在的安全問題。它可以識別常見的代碼漏洞、敏感信息泄露和其他安全 ...
  • # What is Polymorphism 這個多態看中文確實有點費解,多態的英文是Polymorphism,它的翻譯含義是: n. 多態性 (可以看出是比較寬泛的) n. 多型現象 從翻譯也看不出啥, 我舉一個生活中的例子來引入多態: 生活中有很多常見的物體具有多態性。例如,一張紙可以用來寫字、 ...
  • # 個人博客-給文章添加上標簽 # 優化計劃 - [x] 置頂3個且可滾動或切換 - [x] 推薦改為4個,然後新增歷史文章,將推薦的載入更多放入歷史文章,按文章發佈時間降序排列。 - [x] 標簽功能,可以為文章貼上標簽 - [ ] 推薦點贊功能 本篇文章實現文章標簽功能 # 思路 > 首先需要新 ...
  • # .NET Evolve資料庫版本管理工具 ## 1.簡介 提到資料庫版本管理,`Java`領域開發首先會想到大名鼎鼎的`flyway`。但是它不適用`.NET`領域,那麼`.NET`領域也需要做資料庫版本管理,該用什麼工具?自行造輪子?`.NET`領域的解決方案就是`Evolve`,這是一個開源 ...
  • # Ocelot與路由共存 ### 引言 在Asp.Net Core中使用了Ocelot做網關之後,其自身的Api路由就不起作用了,尋了許久的解決方法,終於找到一個,主要是使用MapWhen判斷Ocelot的配置是否符合,是則走轉發路由,否則走自身路由,步驟如下: ### 1.先創建以下類 ``` ...
  • 上篇文章講述了[C#介面的知識點](https://mp.weixin.qq.com/s?__biz=MzI2NDE1MDE1MQ==&mid=2650851371&idx=1&sn=c630043f8d85816c660c53cbf6b3f218&chksm=f14565c3c632ecd5816 ...
  • # UGUI的Button(按鈕)組件的介紹及使用 ## 1. 什麼是UGUI的Button組件? UGUI(Unity GUI)是Unity引擎中的一套用戶界面系統,Button(按鈕)是其中的一個常用組件。Button組件可以用於創建可交互的按鈕,用戶點擊按鈕時可以觸發相應的事件。 ## 2. ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...