{"id":732,"date":"2023-04-01T22:16:44","date_gmt":"2023-04-01T20:16:44","guid":{"rendered":"https:\/\/blog.adameczek.pl\/?p=732"},"modified":"2024-05-11T17:51:10","modified_gmt":"2024-05-11T15:51:10","slug":"znajdz-dzialania-czesc-ii","status":"publish","type":"post","link":"https:\/\/blog.adameczek.pl\/index.php\/2023\/04\/01\/znajdz-dzialania-czesc-ii\/","title":{"rendered":"Znajd\u017a dzia\u0142ania \u2013 cz\u0119\u015b\u0107 II"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Jak wspomnia\u0142em w poptrzednim wpisie na ten temat, zadanie polega na znalezieniu takich dzia\u0142a\u0144, kt\u00f3re wstawione pomi\u0119dzy liczby dadz\u0105 r\u00f3wnianie. Dla utrudnienia, poszczeg\u00f3lne sk\u0142adniki obu cz\u0119\u015bci r\u00f3wno\u015bci mo\u017cna \u0142\u0105czy\u0107 tworz\u0105c liczb\u0119 sk\u0142adaj\u0105c\u0105 si\u0119 z cyfr obu sk\u0142adowych. Nie mo\u017cna przestawia\u0107 kolejno\u015bci sk\u0142adnik\u00f3w ani cyfr w sk\u0142adnikach. Wynik ka\u017cdego dzia\u0142ania musi by\u0107 liczb\u0105 ca\u0142kowit\u0105, a sk\u0142adowe musz\u0105 by\u0107 liczb\u0105 ca\u0142kowit\u0105 dodatni\u0105. Dla przyk\u0142adu dane sk\u0142adowe 1 i 23 mo\u017cna zestawi\u0107 tak:<br>1 + 23<br>1 &#8211; 23<br>1 * 23<br>123<br>(1 \/ 23 odpada, bo wynik dzielenia pozostawia reszt\u0119)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Program b\u0119dzie wykonywa\u0142 sekwencj\u0119:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Przyjmie dane wej\u015bciowe<\/li>\n\n\n\n<li>Wygeneruje mo\u017cliwe kombinacje dla obu stron r\u00f3wniania<\/li>\n\n\n\n<li>Policzy warto\u015b\u0107 ka\u017cdego wyra\u017cenia eliminuj\u0105c te, kt\u00f3re nie spe\u0142niaj\u0105 wymagania dzielenia bez reszty<\/li>\n\n\n\n<li>Znajdzie kombinacje obu stron r\u00f3wnania, kt\u00f3re mo\u017cna zestawi\u0107 ze sob\u0105 (daj\u0105 r\u00f3wno\u015b\u0107)<\/li>\n\n\n\n<li>Wy\u015bwietli wyniki<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">W tym wpisie zajm\u0119 si\u0119 utworzeniem wyra\u017ce\u0144 dla jednej strony r\u00f3wnania. W kolejnych wpisach, kiedy b\u0119d\u0105 obliczane warto\u015bci wyra\u017ce\u0144 (punkt 3), wywo\u0142amy kod dwuktotnie. Cz\u0119\u015b\u0107 1 i 5 b\u0119d\u0105 pokazane na ko\u0144cu, kiedy zbudowana zostanie aplikacja Blazor a z ni\u0105 interfejs u\u017cytkownika.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Na pocz\u0105tek utworzymy obiekt &#8211; model wyra\u017cenia. B\u0119dzie on zawiera\u0142 list\u0119 sk\u0142adowych i list\u0119 dzia\u0142a\u0144 matematycznych. Opr\u00f3cz tego zapiszemy wynik wyra\u017cenia oraz flag\u0119 wskazuj\u0105c\u0105, czy dzia\u0142anie jest wa\u017cne czy te\u017c b\u0142\u0119dne. Zdefiniujmy te\u017c dozwolone dzia\u0142ania matematyczne.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism off-numbers lang-csharp\" data-file=\"Expression.cs\" data-lang=\"C#\"><code>public class Expression\n{\n    public List&lt;int&gt; Numbers { get; set; } = new();\n    public List&lt;OperationType&gt; Operations { get; set; } = new();\n    public int? CalculatedResult { get; set; }\n    public bool ErrorOccured { get; set; }\n}\n\npublic enum OperationType\n{\n    Add,\n    Substract,\n    Multiplicate,\n    Divide\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">W\u0142a\u015bciwo\u015bci <code>Numbers<\/code> i <code>Operations <\/code>s\u0105 od razu inicjalizowane, bo za chwil\u0119 b\u0119d\u0105 w nich przechowywane kolejne elementy. Dla wyra\u017cenia '1+23&#8242; instancja <code>Expression<\/code> b\u0119dzie zawiera\u0142a w li\u015bcie <code>Numbers<\/code> kolejno liczby 1, 23 a <code>Operations<\/code> jedn\u0105 z operacji. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wykonajmy metod\u0119 buduj\u0105c\u0105 te wyra\u017cenia. Znajdzie si\u0119 ona w klasie <code>ExpressionBuilder<\/code>. Wyra\u017cenia b\u0119d\u0105 budowane od lewej. Wej\u015bciowa lista liczb, np. 1, 2, 3 b\u0119dzie dzielona na liczby z lewej strony operacji oraz na te z prawej strony. Pomi\u0119dzy nie wstawiamy po kolei operacje Add, Substract, Multiplicate, Divide. Na pocz\u0105tku pozycja podzia\u0142u znajduje si\u0119 pomi\u0119dzy 1 (<em>leftHandNumbers <\/em>linia 13) a 2 i 3  (rightHandNumbers linia 19). W linii 14 wywo\u0142ywana jest funkcja <code>GetPartialExpressions<\/code>, do kt\u00f3rej przekazywane s\u0105 <em>leftHandNumbers<\/em> i ca\u0142e wyra\u017cenie. Tam tworzone s\u0105 operacje cz\u0119\u015bciowe 1+, 1-, 1* i 1\/. Funkcja zwraca wyliczenie takich cz\u0119\u015bciowych operacji.  Potem w linii 18-20 do ka\u017cdej z operacji cz\u0119\u015bciowych dodawana jest nowa liczba powsta\u0142a z po\u0142\u0105czenia sk\u0142adnik\u00f3w <em>rightHandNumbers<\/em> (dla naszego przyk\u0142adu jest to 23), a ca\u0142e wyra\u017cenie (1+23, 1-23 1*23, 1\/23) dodawane do listy gotowych wyra\u017ce\u0144 (linia 21). Nast\u0119pnie rekurencyjnie wo\u0142amy metod\u0119 <code>CreateExpressions<\/code> dla ka\u017cdego elementu <em>partialExpression<\/em> przekazuj\u0105c <em>rightHandNumbers<\/em> (liczby 2 i 3). Co si\u0119 tam wydarzy? Do ka\u017cdego wyra\u017cenia cz\u0119\u015bciowego zostan\u0105 dobudowane kolejne:<br>1+2+<br>1+2-<br>1+2*<br>1+2\/<br>1-2+<br>1-2-<br>&#8230;.. i tak dalej.<br>Potem zn\u00f3w zostanie wywo\u0142ana rekurencyjnie  <code>CreateExpressions<\/code>. I tak do momentu, a\u017c zabraknie sk\u0142adowych po prawej stronie i nie da si\u0119 przesun\u0105\u0107 wska\u017anika <em>position<\/em> w prawo. Przypadek z trzema sk\u0142adowymi jest jeszcze prosty, ale przy wi\u0119kszej ich liczbie pojawiaj\u0105 si\u0119 wyra\u017cenia bardziej z\u0142o\u017cone, np. 123 + 4 &#8211; 56 \/ 7 * 6 &#8211; 89.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-csharp\" data-file=\"ExpressionBuilder.cs\" data-lang=\"C#\"><code>public class ExpressionBuilder\n{\n    private List&lt;Expression&gt; Expressions { get; } = new();\n     \n    private void CreateExpressions(ICollection&lt;int&gt; numbers, Expression? expression = null)\n    {\n        var position = 0;\n\n        while (position &lt; numbers.Count - 1)\n        {\n            ++position;\n\n            var leftHandNumbers = numbers.Take(position);\n            var partialExpressions = GetPartialExpressions(leftHandNumbers.ToNumber(), expression);\n            \n            foreach (var partialExpression in partialExpressions)\n            {\n                var newExpression = partialExpression.Clone();\n                var rightHandNumbers = numbers.Skip(position).ToList();\n                newExpression.Numbers.Add(rightHandNumbers.ToNumber());\n                Expressions.Add(newExpression);\n\n                CreateExpressions(rightHandNumbers.ToArray(), partialExpression);\n            }\n        }\n    }\n\n    private static IEnumerable&lt;Expression&gt; GetPartialExpressions(int number, Expression expression)\n    {\n        var newExpressions = new List&lt;Expression&gt;();\n        foreach (var operation in Enum.GetValues&lt;OperationType&gt;())\n        {\n            var newExpression = expression.Clone();\n            newExpression.Numbers.Add(number);\n            newExpression.Operations.Add(operation);\n            newExpressions.Add(newExpression);\n        }\n        return newExpressions;\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Za ka\u017cdym razem, kiedy tworzymy nowe wyra\u017cenie, robimy to na podstawie innego, nie do ko\u0144ca zbudowanego wyra\u017cenia cz\u0119\u015bciowego. To cz\u0119\u015bciowe wyra\u017cenie jest baz\u0105 dla budowy kilku nowych. Za ka\u017cdym razem musi by\u0107 utworzona kompletna kopia w\u0142\u0105czaj\u0105c kopiowanie typ\u00f3w referencyjnych sk\u0142adaj\u0105cych si\u0119 na wyra\u017cenie (metoda <code>Clone<\/code> w liniach 18 i 33). Jest to tzw. <em>deep copy<\/em> <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.object.memberwiseclone?view=net-7.0\">Wi\u0119cej od Microsoftu o kopiowaniu typ\u00f3w<\/a>. Metoda jest sk\u0142adow\u0105 typu Expression. Uzupe\u0142nijmy zatem listing<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-csharp\" data-file=\"Expression.cs\" data-lang=\"C#\"><code>public class Expression\n{\n    public List&lt;int&gt; Numbers { get; set; } = new();\n    public List&lt;OperationType&gt; Operations { get; set; } = new();\n    public int? CalculatedResult { get; set; }\n    public bool ErrorOccured { get; set; }\n\n    public Expression Clone()\n    {\n        var clone = (Expression)MemberwiseClone();\n        clone.Numbers = new List&lt;int&gt;(Numbers);\n        clone.Operations = new List&lt;OperationType&gt;(Operations);\n        return clone;\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Ponadto u\u017cywana jest medoda <code>ToNumber <\/code>rozszerzaj\u0105ca typ <em>IEnumerable&lt;int><\/em>. To ma\u0142a metoda pomocnicza do konkretnego zastosowania. Nie ma sensu tworzy\u0107 jej generycznego odpowiednika, cho\u0107 by\u0142oby to mo\u017cliwe.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-csharp\" data-file=\"Extensions.cs\" data-lang=\"C#\"><code>public static class Extensions\n{\n    public static int ToNumber(this IEnumerable&lt;int&gt; numbers)\n    {\n        return int.Parse(string.Concat(numbers));\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Listing klasy ExpressionBuilder powy\u017cej jest nieco uproszczony, aby nie zaciemnia\u0107 podstawowego kodu tworz\u0105cego wyra\u017cenie. Ale dla pe\u0142nego obrazu przytaczam ca\u0142o\u015b\u0107 z komentarzami w punktach:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Zdefiniowana jest tu metoda GetExpressions, kt\u00f3ra pozwala nasz obiekt poprosi\u0107 o wyniki. Osobi\u015bnie wol\u0119 takie podej\u015bcie, ni\u017c wydawa\u0107 polecenie <code>expressionBuilder.CreateExpressions()<\/code>, a potem odczytywa\u0107 w\u0142a\u015bciwo\u015b\u0107 <code>Expressions<\/code>. Niech procedura wykonania zadania pozostanie wewn\u0119trzn\u0105 spraw\u0105 obiektu. My prosimy tylko o dostarczenie wynik\u00f3w.<\/li>\n\n\n\n<li>Linia 13 rozwi\u0105zuje przypadek brzegowy, kiedy przekazywana kolekcja nie zawiera \u017cadnej liczby.<\/li>\n\n\n\n<li>Sprawdzamy, czy to jest pierwsza iteracja (linia 15) i wtedy dodajemy do wynik\u00f3w wyra\u017cenie z\u0142o\u017cone z po\u0142\u0105czonych liczb nie zawieraj\u0105ce \u017cadnej operacji. Dodatkowo sprawdzany jest warunek brzegowy, czy przekazana kolekcja zawiera pojedyncz\u0105 liczb\u0119. Je\u015bli tak, to jest ona jedynym sk\u0142adniniej wyra\u017cenia i metoda ko\u0144czy prac\u0119 (linia 20).<\/li>\n\n\n\n<li>Piersze wywo\u0142anie <code>GetPartialExpressions<\/code> (przy pierwszej iteracji) przekazuje nowy 'pusty&#8217; obiekt <code>Expression<\/code> (linia 31).<\/li>\n<\/ol>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-csharp\" data-file=\"ExpressionBuilder.cs\" data-lang=\"C#\"><code>public class ExpressionBuilder\n{\n    private List&lt;Expression&gt; Expressions { get; } = new();\n    \n    public List&lt;Expression&gt; GetExpressions(ICollection&lt;int&gt; numbers)\n    {\n        CreateExpressions(numbers);\n        return Expressions;\n    }\n    \n    private void CreateExpressions(ICollection&lt;int&gt; numbers, Expression? expression = null)\n    {\n        if (!numbers.Any()) return;\n\n        if (expression is null)\n        {\n            var newExpression = new Expression();\n            newExpression.Numbers.Add(numbers.ToNumber());\n            Expressions.Add(newExpression);\n            if (numbers.Count == 1) return;\n        }\n\n        var position = 0;\n\n        while (position &lt; numbers.Count - 1)\n        {\n            ++position;\n\n            var leftHandNumbers = numbers.Take(position);\n            var partialExpressions = GetPartialExpressions(leftHandNumbers.ToNumber(), \n                expression ??= new Expression());\n            \n            foreach (var partialExpression in partialExpressions)\n            {\n                var newExpression = partialExpression.Clone();\n                var rightHandNumbers = numbers.Skip(position).ToList();\n                newExpression.Numbers.Add(rightHandNumbers.ToNumber());\n                Expressions.Add(newExpression);\n\n                CreateExpressions(rightHandNumbers.ToArray(), partialExpression);\n            }\n        }\n    }\n\n    private static IEnumerable&lt;Expression&gt; GetPartialExpressions(int number, Expression expression)\n    {\n        var newExpressions = new List&lt;Expression&gt;();\n        foreach (var operation in Enum.GetValues&lt;OperationType&gt;())\n        {\n            var newExpression = expression.Clone();\n            newExpression.Numbers.Add(number);\n            newExpression.Operations.Add(operation);\n            newExpressions.Add(newExpression);\n        }\n        return newExpressions;\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Na koniec uzupe\u0142niamy obiekt <code>Expression<\/code> nasz\u0105 wersj\u0105 metody <code>ToString<\/code>. B\u0119dzie potrzebna przy drukowaniu wynik\u00f3w, kiedy b\u0119dziemy chcieli pokaza\u0107 ka\u017cde wyra\u017cenie w postaci czytelnej dla cz\u0142owieka.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-csharp\" data-file=\"Expression.cs\" data-lang=\"C#\"><code>public class Expression\n{\n    \/\/ tu kod z poprzedniego listingu klasy Expression\n\n    public override string ToString()\n    {\n        if (!Operations.Any()) return Numbers.FirstOrDefault().ToString();\n        \n        var sb = new StringBuilder();\n        var position = 0;\n\n        while (position &lt; Operations.Count)\n        {\n            sb.Append(Numbers[position]);\n            switch (Operations[position])\n            {\n                case OperationType.Add:\n                    sb.Append(&quot; + &quot;);\n                    break;\n                case OperationType.Substract:\n                    sb.Append(&quot; - &quot;);\n                    break;\n                case OperationType.Multiplicate:\n                    sb.Append(&quot; * &quot;);\n                    break;\n                case OperationType.Divide:\n                    sb.Append(&quot; \/ &quot;);\n                    break;\n            }\n            ++position;\n        }\n        sb.Append(Numbers.Last());\n        \n        return sb.ToString();\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">To na razie tyle. W nast\u0119pnym wpisie zbudujemy kalkulator, kt\u00f3ry policzy nam warto\u015b\u0107 wyra\u017cenia z zachowaniem kolejno\u015bci dzia\u0142a\u0144.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Jak wspomnia\u0142em w poptrzednim wpisie na ten temat, zadanie polega na znalezieniu takich dzia\u0142a\u0144, kt\u00f3re wstawione pomi\u0119dzy liczby dadz\u0105 r\u00f3wnianie. Dla utrudnienia, poszczeg\u00f3lne sk\u0142adniki obu cz\u0119\u015bci r\u00f3wno\u015bci mo\u017cna \u0142\u0105czy\u0107 tworz\u0105c liczb\u0119 sk\u0142adaj\u0105c\u0105 si\u0119 z cyfr obu sk\u0142adowych. Nie mo\u017cna przestawia\u0107 kolejno\u015bci sk\u0142adnik\u00f3w ani cyfr w sk\u0142adnikach. Wynik ka\u017cdego dzia\u0142ania musi by\u0107 liczb\u0105 ca\u0142kowit\u0105, a sk\u0142adowe [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":822,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ocean_post_layout":"","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"0","ocean_second_sidebar":"0","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"default","ocean_display_header":"default","ocean_header_style":"","ocean_center_header_left_menu":"0","ocean_custom_header_template":"0","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"0","ocean_menu_typo_font_family":"0","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"0","_jetpack_memberships_contains_paid_content":false,"ocean_post_oembed":"","ocean_post_self_hosted_media":"","ocean_post_video_embed":"","ocean_link_format":"","ocean_link_format_target":"self","ocean_quote_format":"","ocean_quote_format_link":"post","ocean_gallery_link_images":"off","ocean_gallery_id":[],"footnotes":""},"categories":[10],"tags":[15],"class_list":["post-732","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net","tag-csharp","entry","has-media"],"jetpack_featured_media_url":"https:\/\/blog.adameczek.pl\/wp-content\/uploads\/2024\/05\/Csharp_logo.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/posts\/732","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/comments?post=732"}],"version-history":[{"count":20,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/posts\/732\/revisions"}],"predecessor-version":[{"id":754,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/posts\/732\/revisions\/754"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/media\/822"}],"wp:attachment":[{"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/media?parent=732"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/categories?post=732"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/tags?post=732"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}