/// <summary>
        /// Applies rules to a pattern and returns the next generation
        /// </summary>
        /// <param name="cells">current </param>
        /// <returns>the next generation pattern after applying Life rules</returns>
        public async Task <LifeBoardInt> GetNextGeneration(LifeBoardInt cells)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                await JsonSerializer.SerializeAsync <LifeBoardInt>(ms, cells).ConfigureAwait(false);

                ms.Position = 0;
                using (StreamReader sr = new StreamReader(ms))
                {
                    var str = sr.ReadToEnd();

                    using (StringContent body = new StringContent(str, Encoding.UTF8, "application/json"))
                    {
                        var response = await _httpClient.PostAsync(new Uri("conwaylife", UriKind.Relative), body).ConfigureAwait(false);

                        response.EnsureSuccessStatusCode();

                        using (var responseStream
                                   = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                        {
                            return(await JsonSerializer.DeserializeAsync
                                   <LifeBoardInt>(responseStream).ConfigureAwait(false));
                        }
                    }
                }
            }
        }
        static public ILifeBoard FromPattern(IEnumerable <string> initialRows)
        {
            if (initialRows == null)
            {
                throw new ArgumentNullException(nameof(initialRows));
            }

            if (initialRows.Any(l => l == null))
            {
                throw new ArgumentOutOfRangeException(nameof(initialRows));
            }

            int rowCount = initialRows.Count();

            if (rowCount == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(initialRows));
            }

            int colCount = initialRows.Max(l => l.Length);

            if (colCount == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(initialRows));
            }

            if (rowCount > GetMaxRows() || colCount > GetMaxColumns())
            {
                throw new ArgumentOutOfRangeException(nameof(initialRows));
            }

            ILifeBoard cells = new LifeBoardInt(rowCount, colCount, 0, null);

            int rowNum = 0;

            foreach (var row in initialRows)
            {
                var l = row;
                if (l.Length < colCount)
                {
                    l = l + new string('0', colCount - l.Length);
                }

                for (int c = 0; c < colCount; c++)
                {
                    cells[rowNum, c] = l[c] == '1' || l[c] == 'X';
                }
                rowNum++;
            }
            return(cells);
        }