Оптимальні літерні картки для написання слів


15

Скажімо, у вас є список слів, і ви хочете мати можливість використовувати літерні картки для написання кожного слова. Наприклад, для написання кота ви б використали три картки з позначкою C, A, T.

Припускаючи, що кожна картка є двосторонньою , подайте програму для визначення мінімальної кількості карток, за допомогою яких можна написати весь список слів.

Введення - це список слів, він може бути файловим, жорстко кодованим, командним рядком, будь-яким іншим. Вихід - це перелік карт, відформатований та упорядкований так, як Ви вважаєте за потрібне, за умови, що зрозуміло, як картки маркуються.

Справа не суттєва: гольф, гольф та GOLF рівноцінні.

Деякі підказки:

  • кількість карток може бути не менше довжини найдовшого слова
  • для картки немає сенсу мати однаковий лист з обох сторін
  • хоча випадок не є важливим, рекомендуйте використовувати малі регістри, щоб скористатися певними симетріями

Наприклад, вони використовують певні симетрії :

Вхідні дані: бен, болото, помилка, лігво, ду, лань, собака, належне, викопано, Ед, кінець, бог, Бог, Нед, Ода, перо, По, Мопс

Вихід: b / d, e / g, o / n

Введення: an, і, ape, are, be, bed, bud, bur, Dan, Deb, dub, ear, Ed, era, дрімота, pan, горох, паб, Rae, побіг, руб

Вихід: a / b, d / r, e / n

Зробити це популярним змаганням, тому важлива елегантність коду, виконання часу та кмітливість (включаючи вигин правил і лазівки)!

Доповнення : Деякі запитували про "дозволені" симетрії, чи можна використовувати спеціальні шрифти та чи можна складати карти.

Дозволені симетрії - це будь-які літери, схожі між собою після обертання 0, 90, 180 або 270 градусів. Сюди входять b / q, d / p та n / u. Я б також сказав M / W, Z / N, і, звичайно, I / l (літери i, малі L). Я, мабуть, дряпаю поверхню, тому, якщо є інші, про які ви не впевнені, просто запитайте.

Щоб зробити це просто, обмежтеся стандартним шрифтом sans-serif, скажімо, що використовується в SE.

Що стосується складання, тоді як ви можете зробити дивовижні заміни, наприклад, B може бути D, E, F, I, P або R, а може бути, C або L, якщо ви складете по-справжньому креативно, я думаю, що це згинання, буквально, занадто багато !

Я зіткнувся з цією проблемою, граючи в якісь подібні карти зі своїми дітьми. Я зазначив, наскільки легко було придумати односторонні картки порівняно з тим, як важко було придумати двосторонні картки.

Доповнення : надали нагороду за найпопулярнішу відповідь. Якщо буде нічия, нагородить того, хто подав перше.

Ще одна підказка:

  • вирішення однобічної проблеми дасть вам уявлення про мінімальну кількість необхідних карток (наприклад, 20 односторонніх карт перекладається на щонайменше 10 двосторонніх карт)

Додаток : О, турбуйся, я був зайнятий і забув про закінчення щедрості. Це закінчилося нікому, тому що єдина відповідь була подана ще до того, як почався щедрість! Вибач за це.


3
Просто для уточнення, що дозволено? Є тільки пари симетрії n/u, d/p? Що про b/qі m/w? А що, якщо я складу Pкартку на два, щоб стала верхня половина D?
Sp3000

3
1. Чи є їх перелік затверджених "симетрій", я вважаю, що він може відрізнятися залежно від шрифту, який є потенційним отвором циклу (використовуйте шрифт, у якому символи однакові, тобто картки завжди будуть дорівнювати / або щось подібне) 2. "Справа не суттєва", тому "N" може бути представлена ​​"u"?
Девід Роджерс

Я думаю, ви робите своє питання несправедливістю, роблячи це конкурсом популярності. Ви не проявляєте творчості, кажучи людям бути творчими, ви отримуєте це, поставивши їм важкий виклик і змусивши їх вичавити все, що можуть.
xnor

@ sp3000 - b / q звичайно. Щодо інших ваших питань, я уточню правила.

1
Вважати це за конкурс популярності (не кажучи вже про щедроту) - не зовсім правильно. Яка гарантія, що відповіді оптимальні? Що робити, якщо одна відповідь дає неоптимальний результат, але з якихось причин має найбільше голосів ..
Оптимізатор

Відповіді:


5

C # - CardChooser

Підсумок

Ця програма використовує метод грубої сили для спроби вирішити кожен список. Спочатку я створюю список потенційних карток для вибору, потім я визначаю, яка найкраще підходить (видаляє найбільше символів + найбільше скорочує довгі слова), додаю це до списку результатів і продовжую цей процес, поки я не вибрав достатньо потенційних карт щоб видалити кожне слово зі списку, після чого я повторюю ці картки до кожного слова та друкую висновок.

Якщо ви хочете побачити більш обмежену версію цього коду без завантаження та створення наданого додатка форм Windows, ви можете використовувати посилання, яке надається для запуску моєї програми на менших наборах даних, зауважте, що це консольна версія програми, тому отримана картки НЕ обертаються: http://ideone.com/fork/VD1gJF

Історія редагування

Поточний - Додано кращу оптимізацію результатів, запропоновану @Zgarb

Оновлення 3 - Більше очищення коду, більше виправлених помилок, кращі результати

Оновлення 2 - Форми Windows, Більш докладний висновок

Оновлення 1 - Нова / краща підтримка симетрій символів

Оригінал - додаток консолі

Приклади

acr, aft, ain, sll, win, скажімо, сказав, швидкий, епічний Вихід 0

гес, буде, з, не буде, хотів би, не хотів би, все-таки, ти, юд, ти будеш Вихід 1

aaaa, bbbb, cccc
Вихід 2

Код

Мені все-таки потрібно поєднати це в одному великому проекті з кодом ConsoleApp і WindowsForms, який використовує однакові класи і методи, а потім розділити різні регіони методом RunButton_Click, щоб я могла писати одиниці навколо них, у будь-якому разі, коли знайду час для цього. Буду, поки що це:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace CardChooserForms
{
    public partial class CardChooser : Form
    {
        private class Solution : IEquatable<Solution>
        {
            public List<string> Cards { get; set; }
            public List<string> Remaining { get; set; }

            public int RemainingScore
            {
                get
                {
                    return this.Remaining.Sum(b => b.ToCharArray().Count());
                }
            }

            public bool Equals(Solution other)
            {
                return new string(Cards.OrderBy(a => a).SelectMany(a => a).ToArray()) == new string(other.Cards.OrderBy(a => a).SelectMany(a => a).ToArray());
            }

            public override int GetHashCode()
            {
                return (new string(Cards.OrderBy(a => a).SelectMany(a => a).ToArray())).GetHashCode();
            }
        }
        private class Symmetry
        {
            public char Value { get; set; }
            public Int16 RotationDifference { get; set; }
        }

        /// <summary>
        /// This is where Symmetries are stored, right now it only has support for pairs(two values per array)
        /// </summary>
        private static Symmetry[][] _rotatableCharacters = new Symmetry[][] {                 
                new Symmetry[] { new Symmetry {Value = 'Z'}, new Symmetry {Value = 'N', RotationDifference = 90}}, 
                new Symmetry[] { new Symmetry {Value = 'd'}, new Symmetry {Value = 'p', RotationDifference = 180 }}, 
                new Symmetry[] { new Symmetry {Value = 'u'}, new Symmetry {Value = 'n', RotationDifference = 180 }}, 
                new Symmetry[] { new Symmetry {Value = 'm'}, new Symmetry {Value = 'w', RotationDifference = 180 }}, 
                new Symmetry[] { new Symmetry {Value = 'b'}, new Symmetry {Value = 'q', RotationDifference = 180 }}, 
                new Symmetry[] { new Symmetry {Value = 'l'}, new Symmetry {Value = 'I', RotationDifference = 0}},                 
            };

        //These all control the output settings
        private readonly static int _defualtSpacing = 25;
        private readonly static int _defualtFontSize = 8;
        private readonly static Font _defualtFont = new Font("Microsoft Sans Serif", _defualtFontSize);
        private readonly static Brush _defualtBackgroundColor = Brushes.Beige;
        private readonly static Brush _defualtForegroundColor = Brushes.Black;


        public CardChooser()
        {
            InitializeComponent();
        }

        private void RunButton_Click(object sender, EventArgs e)
        {            
            #region Input Parsing
            //Get input                         
            string input = InputRichTextBox.Text;

            if (!input.Contains(","))
                throw new ArgumentException("Input must contain more than one value and must be seprated by commas.");

            //Parse input
            var inputLowercasedTrimedTransformed = input.Split(',').Select(a => a.ToLowerInvariant().Trim()).ToArray();
            var inputSplitTrimIndex = input.Split(',').Select(a => a.Trim()).ToArray().Select((a, index) => new { value = a, index }).ToArray();
            #endregion Input Parsing

            #region Card Formation
            var inputCharParsed = inputLowercasedTrimedTransformed.Select(a => a.ToCharArray()).ToArray();
            var possibleCards = GetAllCasesTwoLengthArrayElements(
                UniqueBiDirection(
                //Get unique characters
                    inputCharParsed
                    .SelectMany(a => a)
                    .Distinct()
                    .Select(a => new
                    {
                        Character = a,
                        PossibleCharacters = inputCharParsed.SelectMany(b => b).Where(b => b != a).ToList()
                    })
                //Now get distinct cards(ie NB == BN, NB != NE)
                    .SelectMany(a => a.PossibleCharacters.Select(b => new string(new char[] { a.Character, b })).ToArray()).ToArray()
                    ).ToArray()
                ).ToArray();

            //Now get every possible character each card can eliminate
            var possibleCharsFromCards = GetAllPossibleCharsFromACards(possibleCards).ToArray();

            //Now set up some possibilities that contain only one card
            var possibleCardCombinations = possibleCards.Select((a, index) => new Solution
            {
                Cards = new List<string> { a },
                //Use the index of each card to reference the possible characters it can remove, then remove them per card to form a initial list of cards
                Remaining = inputLowercasedTrimedTransformed.Select(b => b.RemoveFirstInCharArr(possibleCharsFromCards[index].ToLowerInvariant().ToCharArray())).ToList()
            })
            //Take the best scoring card, discard the rest
            .OrderBy(a => a.RemainingScore)
            .ThenBy(a => a.Remaining.Max(b => b.Length))
            .Take(1).ToList();
            #endregion Card Formation

            #region Card Selection
            //Find best combination by iteratively trying every combination + 1 more card, and choose the lowest scoring one 
            while (!possibleCardCombinations.Any(a => a.Remaining.Sum(b => b.ToCharArray().Count()) == 0) && possibleCardCombinations.First().Cards.Count() < possibleCards.Count())
            {
                //Clear the list each iteration(as you can assume the last generations didn't work
                var newPossibilites = new List<Solution>();
                var currentRoundCardCombinations = possibleCardCombinations.ToArray();
                possibleCardCombinations.Clear();

                foreach (var trySolution in currentRoundCardCombinations)
                    foreach (var card in possibleCards.Select((a, index) => new { value = a, index }).Where(a => !trySolution.Cards.Contains(a.value)).ToArray())
                    {
                        var newSolution = new Solution();
                        newSolution.Cards = trySolution.Cards.ToList();
                        newSolution.Cards.Add(card.value);
                        newSolution.Remaining = trySolution.Remaining.ToList().Select(a => a.RemoveFirstInCharArr(possibleCharsFromCards[card.index].ToLowerInvariant().ToCharArray())).ToList();
                        newPossibilites.Add(newSolution);
                    }

                //Choose the highest scoring card
                possibleCardCombinations = newPossibilites
                    .OrderBy(a => a.RemainingScore)
                    .ThenBy(a => a.Remaining.Max(b => b.Length))
                    .Distinct().Take(1).ToList();
            }
            var finalCardSet = possibleCardCombinations.First().Cards.ToArray();
            #endregion Card Selection

            #region Output
            using (var image = new Bitmap(500, inputSplitTrimIndex.Count() * _defualtSpacing + finalCardSet.Count() * (_defualtFontSize / 2) + _defualtSpacing))
            using (Graphics graphic = Graphics.FromImage(image))
            {
                //Background
                graphic.FillRectangle(_defualtBackgroundColor, 0, 0, image.Width, image.Height);

                //Header                
                graphic.DrawString("Total Number of Cards Required: " + finalCardSet.Count(), _defualtFont, _defualtForegroundColor, new PointF(0, 0));
                graphic.DrawString(
                    "Cards: " + String.Join(", ", finalCardSet.Select(a => a[0] + "/" + a[1])),
                    _defualtFont,
                    _defualtForegroundColor,
                    new RectangleF(0, _defualtSpacing, image.Width - _defualtSpacing, finalCardSet.Count() * 5));

                //Results
                foreach (var element in inputSplitTrimIndex)
                {
                    //Paint the word
                    graphic.DrawString(element.value + " -> ", _defualtFont, _defualtForegroundColor, new PointF(0, element.index * _defualtSpacing + finalCardSet.Count() * (_defualtFontSize / 2) + _defualtSpacing));

                    //Now go through each character, determining the matching card, and wether that card has to be flipped
                    foreach (var card in GetOrderedCardsRequired(inputLowercasedTrimedTransformed[element.index].ToLowerInvariant(), finalCardSet.ToArray()).ToArray().Select((a, index) => new { value = a, index }))
                        using (var tempGraphic = Graphics.FromImage(image))
                        {
                            //For cards that need to flip
                            if (Char.ToUpperInvariant(element.value[card.index]) != Char.ToUpperInvariant(card.value[0]) &&
                                Char.ToUpperInvariant(element.value[card.index]) != Char.ToUpperInvariant(card.value[1]))
                            {
                                //TODO this is hacky and needs to be rethought
                                var rotateAmount = _rotatableCharacters
                                    .OrderByDescending(a => a.Any(b => b.Value == Char.ToLowerInvariant(element.value[card.index])))
                                    .First(a => a.Any(b => Char.ToUpperInvariant(b.Value) == Char.ToUpperInvariant(element.value[card.index])))
                                    [1].RotationDifference;

                                //Rotate
                                tempGraphic.TranslateTransform(
                                    _defualtSpacing * (_defualtFontSize / 2) + card.index * _defualtSpacing + (rotateAmount == 90 ? 0 : _defualtSpacing / 2) + (rotateAmount == 180 ? -(_defualtSpacing / 4) : 0),
                                    finalCardSet.Count() * (_defualtFontSize / 2) + _defualtSpacing + element.index * _defualtSpacing + (rotateAmount == 180 ? 0 : _defualtSpacing / 2));
                                tempGraphic.RotateTransform(rotateAmount);

                                //Print string
                                tempGraphic.DrawString(
                                String.Join("/", card.value.ToCharArray().Select(a => new string(new char[] { a })).ToArray()),
                                _defualtFont,
                                Brushes.Black,
                                new RectangleF(-(_defualtSpacing / 2), -(_defualtSpacing / 2), _defualtSpacing, _defualtSpacing));
                            }
                            else
                                tempGraphic.DrawString(
                                     String.Join("/", card.value.ToCharArray().Select(a => new string(new char[] { a })).ToArray()),
                                     _defualtFont,
                                     _defualtForegroundColor,
                                     new RectangleF(
                                         _defualtSpacing * (_defualtFontSize / 2) + card.index * _defualtSpacing,
                                         finalCardSet.Count() * (_defualtFontSize / 2) + _defualtSpacing + element.index * _defualtSpacing,
                                         _defualtSpacing, _defualtSpacing));
                        }
                }

                OutputPictureBox.Image = new Bitmap(image);
            }
            #endregion Output
        }

        private IEnumerable<string> GetAllPossibleCharsFromACards(string[] cards)
        {
            return cards.Select(a => 
                new string(a.ToCharArray().Concat(_rotatableCharacters
                                    .Where(b => b.Select(c => c.Value).Intersect(a.ToCharArray()).Count() > 0)
                                    .SelectMany(b => b.Select(c => c.Value))
                                    .Distinct().ToArray()).Distinct().ToArray()));
        }

        private IEnumerable<string> GetOrderedCardsRequired(string word, string[] cards)
        {
            var solution = new List<string>();
            var tempCards = GetAllPossibleCharsFromACards(cards).Select((a, index) => new { value = a, index }).ToList();

            foreach (var letter in word.ToCharArray())
            {
                //TODO this still could theoretically fail I think                
                var card = tempCards
                    //Order by the least number of characters match
                    .OrderBy(a => word.ToLowerInvariant().Intersect(a.value.ToLowerInvariant()).Count())
                    .ThenByDescending(a => tempCards.Sum(b => b.value.ToLowerInvariant().Intersect(a.value.ToLowerInvariant()).Count()))
                    //Then take the least useful card for the other parts of the word
                    .First(a => a.value.ToLowerInvariant().Contains(Char.ToLowerInvariant(letter)));
                solution.Add(cards[card.index]);
                tempCards.Remove(card);
            }
            return solution;
        }

        private static IEnumerable<string> UniqueBiDirection(string[] input)
        {
            var results = new List<string>();
            foreach (var element in input)
                if (!results.Any(a => a == new string(element.ToCharArray().Reverse().ToArray()) || a == element))
                    results.Add(element);
            return results;
        }

        private static IEnumerable<string> GetAllCasesTwoLengthArrayElements(string[] input)
        {
            if (input.Any(a => a.Length != 2))
                throw new ArgumentException("This method is only for arrays with two characters");

            List<string> output = input.ToList();
            foreach (var element in input)
            {
                output.Add(new string(new char[] { Char.ToUpperInvariant(element[0]), Char.ToUpperInvariant(element[1]) }));
                output.Add(new string(new char[] { element[0], Char.ToUpperInvariant(element[1]) }));
                output.Add(new string(new char[] { Char.ToUpperInvariant(element[0]), element[1] }));
            }
            return output;
        }

        private void SaveButton_Click(object sender, EventArgs e)
        {
            using (var image = new Bitmap(OutputPictureBox.Image))
                image.Save(Directory.GetCurrentDirectory() + "Output.png", ImageFormat.Png);
        }
    }

    public static class StringExtensions
    {
        public static string RemoveFirstInCharArr(this string source, char[] values)
        {
            var tempSource = source.ToUpperInvariant();
            foreach (var value in values)
            {
                int index = tempSource.IndexOf(Char.ToUpperInvariant(value));
                if (index >= 0) return source.Remove(index, 1);
            }
            return source;
        }        
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CardChooserForms
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new CardChooser());
        }
    }
}


namespace CardChooserForms
{
    partial class CardChooser
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.InputRichTextBox = new System.Windows.Forms.RichTextBox();
            this.EnterInputLabel = new System.Windows.Forms.Label();
            this.RunButton = new System.Windows.Forms.Button();
            this.OutputPictureBox = new System.Windows.Forms.PictureBox();
            this.OutputPanel = new System.Windows.Forms.Panel();
            this.SaveButton = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.OutputPictureBox)).BeginInit();
            this.OutputPanel.SuspendLayout();
            this.SuspendLayout();
            // 
            // InputRichTextBox
            // 
            this.InputRichTextBox.Location = new System.Drawing.Point(60, 40);
            this.InputRichTextBox.Name = "InputRichTextBox";
            this.InputRichTextBox.Size = new System.Drawing.Size(400, 100);
            this.InputRichTextBox.TabIndex = 0;
            this.InputRichTextBox.Text = "";
            // 
            // EnterInputLabel
            // 
            this.EnterInputLabel.AutoSize = true;
            this.EnterInputLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.EnterInputLabel.Location = new System.Drawing.Point(57, 20);
            this.EnterInputLabel.Name = "EnterInputLabel";
            this.EnterInputLabel.Size = new System.Drawing.Size(81, 17);
            this.EnterInputLabel.TabIndex = 1;
            this.EnterInputLabel.Text = "Enter Input:";
            // 
            // RunButton
            // 
            this.RunButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.RunButton.Location = new System.Drawing.Point(60, 147);
            this.RunButton.Name = "RunButton";
            this.RunButton.Size = new System.Drawing.Size(180, 52);
            this.RunButton.TabIndex = 2;
            this.RunButton.Text = "Run";
            this.RunButton.UseVisualStyleBackColor = true;
            this.RunButton.Click += new System.EventHandler(this.RunButton_Click);
            // 
            // OutputPictureBox
            // 
            this.OutputPictureBox.Location = new System.Drawing.Point(3, 3);
            this.OutputPictureBox.Name = "OutputPictureBox";
            this.OutputPictureBox.Size = new System.Drawing.Size(500, 500);
            this.OutputPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
            this.OutputPictureBox.TabIndex = 3;
            this.OutputPictureBox.TabStop = false;
            // 
            // OutputPanel
            // 
            this.OutputPanel.AutoScroll = true;
            this.OutputPanel.Controls.Add(this.OutputPictureBox);
            this.OutputPanel.Location = new System.Drawing.Point(4, 205);
            this.OutputPanel.Name = "OutputPanel";
            this.OutputPanel.Size = new System.Drawing.Size(520, 520);
            this.OutputPanel.TabIndex = 4;
            // 
            // SaveButton
            // 
            this.SaveButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.SaveButton.Location = new System.Drawing.Point(280, 147);
            this.SaveButton.Name = "SaveButton";
            this.SaveButton.Size = new System.Drawing.Size(180, 52);
            this.SaveButton.TabIndex = 5;
            this.SaveButton.Text = "Save";
            this.SaveButton.UseVisualStyleBackColor = true;
            this.SaveButton.Click += new System.EventHandler(this.SaveButton_Click);
            // 
            // CardChooser
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(534, 737);
            this.Controls.Add(this.SaveButton);
            this.Controls.Add(this.RunButton);
            this.Controls.Add(this.EnterInputLabel);
            this.Controls.Add(this.InputRichTextBox);
            this.Controls.Add(this.OutputPanel);
            this.Name = "CardChooser";
            this.Text = "Card Chooser";
            ((System.ComponentModel.ISupportInitialize)(this.OutputPictureBox)).EndInit();
            this.OutputPanel.ResumeLayout(false);
            this.OutputPanel.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.RichTextBox InputRichTextBox;
        private System.Windows.Forms.Label EnterInputLabel;
        private System.Windows.Forms.Button RunButton;
        private System.Windows.Forms.PictureBox OutputPictureBox;
        private System.Windows.Forms.Panel OutputPanel;
        private System.Windows.Forms.Button SaveButton;
    }
}

1
Як правопис "може" без iкартки?
Клавдіу

"звичайно, I / l (з великої літери i, з нижнього регістру L)", тому нижній регістр l повинен виступати за столицю I.
Девід Роджерс

о, здається, вам слід вказати, що у виході
Клавдіу

@Claudiu Так, я подумав про це на деякий час, це дійсно зводиться до другого питання, яке я задав Йіміну Ронгу, і я думаю, що він правильно це пояснив, якщо я вивожу "l" у карту, це слід зробити так само, як приклади, що це може використовуватися як для верхнього обкладеного I, так і для нижнього l, що призведе до результату, який не відповідає справжньому випадку, але я думаю, що це "добре", оскільки він все ще задовольняє умовам питання, але я знову відкритий для уточнення при необхідності, можливо, в пізнішій версії я можу вивести отримані створені рядки з обернутими символами або щось подібне ...
Девід Роджерс

я думаю, що є помилка. saidОстанній лист не W або p
гордий haskeller
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.