Monday, June 19, 2023

 

#codingexercise

Make Array Zero by Subtracting Equal Amounts 

You are given a non-negative integer array nums. In one operation, you must: 

Choose a positive integer x such that x is less than or equal to the smallest non-zero element in nums. 

Subtract x from every positive element in nums. 

Return the minimum number of operations to make every element in nums equal to 0. 

  

Example 1: 

Input: nums = [1,5,0,3,5] 

Output: 3 

Explanation: 

In the first operation, choose x = 1. Now, nums = [0,4,0,2,4]. 

In the second operation, choose x = 2. Now, nums = [0,2,0,0,2]. 

In the third operation, choose x = 2. Now, nums = [0,0,0,0,0]. 

Example 2: 

Input: nums = [0] 

Output: 0 

Explanation: Each element in nums is already 0 so no operations are needed. 

  

Constraints: 

1 <= nums.length <= 100 

0 <= nums[i] <= 100 

 

import java.util.*; 

import java.util.stream.*; 

class Solution { 

    public int minimumOperations(int[] nums) { 

        List<Integer> list = Arrays.stream(nums).boxed().collect(Collectors.toList()); 

        var nonZero = list.stream().filter(x -> x > 0).collect(Collectors.toList()); 

        int count = 0; 

        while(nonZero.size() > 0) { 

            var min = nonZero.stream().mapToInt(x -> x).min().getAsInt(); 

            nonZero = nonZero.stream().map(x -> x - min).filter(x -> x > 0).collect(Collectors.toList()); 

            count++; 

        } 

        return count; 

    } 

} 

 

Input 

nums = 

[1,5,0,3,5] 

Output 

3 

Expected 

3 

 

Input 

nums = 

[0] 

Output 

0 

Expected 

0 

SQL Schema

 

Table: Books

+----------------+---------+

| Column Name    | Type    |

+----------------+---------+

| book_id        | int     |

| name           | varchar |

| available_from | date    |

+----------------+---------+

book_id is the primary key of this table.

 

Table: Orders

+----------------+---------+

| Column Name    | Type    |

+----------------+---------+

| order_id       | int     |

| book_id        | int     |

| quantity       | int     |

| dispatch_date  | date    |

+----------------+---------+

order_id is the primary key of this table.

book_id is a foreign key to the Books table.

 

Write an SQL query that reports the books that have sold less than 10 copies in the last year, excluding books that have been available for less than one month from today. Assume today is 2019-06-23.

Return the result table in any order.

The query result format is in the following example.

 

Example 1:

Input:

Books table:

+---------+--------------------+----------------+

| book_id | name               | available_from |

+---------+--------------------+----------------+

| 1       | "Kalila And Demna" | 2010-01-01     |

| 2       | "28 Letters"       | 2012-05-12     |

| 3       | "The Hobbit"       | 2019-06-10     |

| 4       | "13 Reasons Why"   | 2019-06-01     |

| 5       | "The Hunger Games" | 2008-09-21     |

+---------+--------------------+----------------+

Orders table:

+----------+---------+----------+---------------+

| order_id | book_id | quantity | dispatch_date |

+----------+---------+----------+---------------+

| 1        | 1       | 2        | 2018-07-26    |

| 2        | 1       | 1        | 2018-11-05    |

| 3        | 3       | 8        | 2019-06-11    |

| 4        | 4       | 6        | 2019-06-05    |

| 5        | 4       | 5        | 2019-06-20    |

| 6        | 5       | 9        | 2009-02-02    |

| 7        | 5       | 8        | 2010-04-13    |

+----------+---------+----------+---------------+

Output:

+-----------+--------------------+

| book_id   | name               |

+-----------+--------------------+

| 1         | "Kalila And Demna" |

| 2         | "28 Letters"       |

| 5         | "The Hunger Games" |

+-----------+--------------------+

 

 

SELECT DISTINCT b.book_id, b.name

FROM books b

LEFT JOIN Orders o on b.book_id = o.book_id

GROUP BY b.book_id, b.name,

DATEDIFF(day, DATEADD(year, -1, '2019-06-23'), o.dispatch_date), 

DATEDIFF(day,  b.available_from, DATEADD(month, -1, '2019-06-23'))

HAVING SUM(o.quantity) IS NULL OR

DATEDIFF(day, DATEADD(year, -1, '2019-06-23'), o.dispatch_date) < 0 OR

(DATEDIFF(day, DATEADD(year, -1, '2019-06-23'), o.dispatch_date) > 0 AND DATEDIFF(day,  b.available_from, DATEADD(month, -1, '2019-06-23')) > 0 AND SUM(o.quantity) < 10);

 

 

Case 1

Input

Books =

| book_id | name | available_from |

| ------- | ---------------- | -------------- |

| 1 | Kalila And Demna | 2010-01-01 |

| 2 | 28 Letters | 2012-05-12 |

| 3 | The Hobbit | 2019-06-10 |

| 4 | 13 Reasons Why | 2019-06-01 |

| 5 | The Hunger Games | 2008-09-21 |

Orders =

| order_id | book_id | quantity | dispatch_date |

| -------- | ------- | -------- | ------------- |

| 1 | 1 | 2 | 2018-07-26 |

| 2 | 1 | 1 | 2018-11-05 |

| 3 | 3 | 8 | 2019-06-11 |

| 4 | 4 | 6 | 2019-06-05 |

| 5 | 4 | 5 | 2019-06-20 |

| 6 | 5 | 9 | 2009-02-02 |

| 7 | 5 | 8 | 2010-04-13 |

Output

| book_id | name |

| ------- | ---------------- |

| 2 | 28 Letters |

| 1 | Kalila And Demna |

| 5 | The Hunger Games |

Expected

| book_id | name |

| ------- | ---------------- |

| 1 | Kalila And Demna |

| 2 | 28 Letters |

| 5 | The Hunger Games |

Sunday, June 18, 2023

 

Translators:

This article introduces a concept that could come handy to overcome some of the drudgery with IaC routines and is a continuation of the previous articles on IaC shortcomings and resolutions. Infrastructure-as-code aka IaC has no hard and fast rules about the use of one form or another to do what it does. At best, it can provide proper scope and better articulation for automation purposes.  The Azure public cloud for instance provides ways to write automation with PowerShell, Command Line interface as well as REST APIs. These cover scripts and for templates, we have different IaC providers such as Azure and Terraform.

Dynamic code generation from an existing form to another is routine and something doable with similar techniques as a compiler does. The set of principles involved is the same. Each unit of IaC can be considered a program and its dependencies can be collected via iterations. With the token and the mappings between one form to another, it is possible to change one set of artifacts to another, say from Azure resource templates to Terraform IaC.

The justification for such a feature is that neither of the IaC providers mentioned would find it in their business interest to provide the tools to convert one form to another even though this is something that they can best do because they already have a runtime to create a plan before applying the IaC. The planning step is the one that understands the IaC and is best suited for tokenizing the IaC.

In the absence of programmability from both IaC providers to expose their internal parsing and translation of their IaC formats, it should be perfectly acceptable to come up with an independent solution that facilitates conversion of one form to another.

This translation involves the following:
1) Lexical analysis This is the part where the compiler divides the text of the program into tokens each of which corresponds to a symbol such as a variable name, keyword, or number.
2) Syntax analysis This is the part where the tokens generated in the previous step are 'parsed' and arranged in a tree-structure (called the syntax tree) that reflects the structure of the program.
3) Type checking This is the part where the syntax tree is analyzed to determine if the program violates certain consistency requirements, for example if a variable is used in a context where the type of the variable doesn't permit.
4) Intermediate code generation This is the part where the program is translated to a simple machine independent intermediate language.
5) Register allocation: This is the part where the symbolic variable names are translated to numbers each of which corresponds to a register in the target machine code.
6) Machine code generation : This is the part where the intermediate language is translated to assembly language for a specific architecture
7) Assembly and linking: This is the part where the assembly language code is translated to binary representation and addresses of variables, functions etc are determined.
The first three parts are called the frontend and the last three parts form the backend.
There are checks and transformation at each step of the processing in the order listed above such that each step passes stronger invariants to the next. The type checker for instance can assume the absence of syntax error.
Lexical analysis is done with regular expressions and precedence rules. Precedence rules are similar to algebraic convention. Regular expressions are transformed into efficient programs using non-deterministic finite automata which consists of a set of states including the starting state and a subset of accepting states and transitions from one state to another on the symbol c. Because they are non-deterministic, compilers use a more restrictive form called deterministic finite automaton. This conversion from a language description written as regular expression into an efficiently executable representation, a DFA, is done by the Lexer generator.
Syntax analysis recombines the token that the lexical analysis split. This results in a syntax tree which has the tokens as the leaves and their left to right sequence is the same as input text. Like in lexical analysis, we rely on building automata and in this case the context free grammars we find can be converted to recursive programs called stack automata. There are two ways to generate such automata, the LL parser (the first L indicates the reading direction and the second L indicates the derivation order) and the SLR parser (S stands for simple)
Symbol tables are used to track the scope and binding of all named objects It supports operations such as initialize an empty symbol table, bind a name to an object, lookup a name in the symbol table, enter a new scope and exit a scope.
Bootstrapping a compiler is interesting because the compiler itself is a program. We resolve this with a quick and dirty compiler or intermediate compilers. 

Saturday, June 17, 2023

 

How to address IaC shortcomings – Part 5?

A previous article discussed a resolution to IaC shortcomings for declaring resources with configuration not yet supported by an IaC repository. This article discusses another scenario where IaC does not suffice and some actions are usually taken outside via pipeline automations and management portal usage. We discuss the naming of app services that must be put behind an application gateway for traffic consolidation and restricting direct access to the app services.

Creating custom names for your Azure resources can be:

 

1.       For usage from WWW:

 

Step 1. Make sure that your Azure resource has public IP connectivity to begin with, otherwise internal names is outlined in the section “For usage in vnet”.

 

Step 2.

Specify an A record in your domain provider

with the following values:

Hostname: <just the hostname part of the default name for your public Azure resource, for eg. App1.azurewebsites.net will have a hostname app1>

IP: The public ip address from Step 1

Domain Name: <cradle>.company.com

AppID : <CostCenterAppId>

User: <your msid>

Admin: AZU_DSI_AZURE_ADMINS

Do not select Force flag or PTR record.

Click Continue

 

Step 3. Specify a CNAME record if you want to reach resources behind the domain you just specified. Note that domains like projectapps.com instead of company.com will force you to create a new A record. If you are not sure whether you want to create an A record or a CNAME record, visit the custom domains feature of your Azure resource, select the “All other domain services” from add custom domain page and enter any domain you like. It will show you two records that you need to have, one of which is an A record or a CNAME record and the other is a TXT record. The TXT record is useful only for validation and once the domain is verified, you can even remove the TXT record. Notice that we are indeed doing the same thing with Steps.2 and 4 in our Optum domain provider.

 

Step 4. Specify the TXT record in the domain provider with the following values.

Hostname: asuid <this is a reserved name>

Type: TXT

VALUE: <domain-identifier-from-the-Azure resource>

 

You could additionally specify a TXT record with the following values, to improve validation because Azure and external providers might have different validation schemes:

Hostname: asverify<this is a reserved name>

TYPE: TXT

VALUE: <default-public-name-that-the-Azure-resource-was-created-with>

 

At present, you don’t need to create any more DNS records.

 

Step 5. Validate the records you have added. Go to: https://dnslookup.online or any toolbox that generates a DIG output and specify the name you have just created in a fully-qualified manner. Wait for the report to show up. Remember that records can take up anywhere from say 1 to 48 hours to fully propagate.



 

2.       For usage in VNet:

 

Names associated with IP addresses do not always need to be registered to nameservers that participate in universal www name resolutions. This is where an Azure DNS resource helps to resolve names. It is also capable of conditionally forwarding dns queries from a virtual network to on-premises DNS servers and other target DNS servers.

 

To create an internal name resolution, you will need an A record and a TXT record.

 

Step 1. Go to Azure DNS from the Azure Portal search bar and create a DNS resource in the same subscription and resource group as the resources you are naming. The name of the DNS resource will be the domain name you want to give to your resource.

 

Step 2. Create an A record / CNAME record as decided by Step 3 in preceding section.

Create the A record with the following value:

Hostname: just the name of the resource without the domain qualifier. The domain name is added automatically.

TYPE: A

VALUE: <default-public-name-that-the-Azure-resource-was-created-with>

 

Step 3: Create a TXT record with the following value:

Hostname: asuid <reserved name>

TYPE: TXT

VALUE: <domain-identifier-from-the-Azure-Resource>

 

Step 4: Create another TXT record with the following value:

Hostname: asverify <reserved name>

TYPE: TXT

VALUE: <default-public-name-that-the-Azure-resource-was-created-with>

 

Step 5. Validate the records you have added. Go to: https://dnslookup.online or any toolbox that generates a DIG output and specify the name you have just created in a fully qualified manner. Wait for the report to show up. Remember that records can take up anywhere from say 1 to 48 hours to fully propagate.



 

 

 

At present, you don’t need to create any more DNS records.

 

A note for application gateway and app services:

 

Initially the A record is registered for app service and the custom name setup for the resource by verifying in the portal.  Then the A record is modified to take the address of the app gateway.

 

 

Friday, June 16, 2023

Application Gateway and Hostname passthrough

Problem statement: Azure public cloud recommends the use of a firewall such as with an application gateway that faces the internet traffic destined to the application services. The app services and the app gateway their own default fully qualified names. Callers sending traffic to the app would want to continue sending the same hostname because this is sent by the browser from various clients and understood by virtually all the elements of the network. When the app services retain their default names and the traffic must come through the application gateway, the hostname is overridden by the gateway for proper routing and the app services are reached by path. This situation is avoided by introducing a custom domain and having the hostname retained but prefixed to the custom domain. There are two steps involved, first each app service in the backend pool of the app gateway must be put in the same custom domain and then the topmost record must be made to point to the application gateway. The problem is that it is hard to add a custom domain to the app service because the validation fails. This article elaborates on the solution.

The process of adding a domain to an app service is made smoother with the use of application domains and application certificates that are managed by Azure. When we specify a custom domain, it can be something other than what Azure provides such as when the apps are part of an organization and there is a top domain. When a domain other than the App Domain is specified, then the portal suggests two DNS records to be added for the application in the DNS Zone corresponding to the domain. These are CNAME record and TXT record when the domain name specified is part of an existing domain such as that of the organization. If the domain name is new and has no parent-child relationship, then the suggested records are A record and TXT record. In these cases, the records other than TXT record point to the default name of the app service while the TXT record points to a hash value specific to the app service. This hash is used to get the app service to join the domain properly and the handshake between the DNS zone for the domain and the app service must validate the TXT record. It is this validation step that fails often for many people.

Other than the purpose of validation, those TXT records can be done away with and the suitable replacement of the top domain with the help of an A record for the application gateway suffices. All these records are identified by a reference to their hostname. These identifiers can include @ for blank values to denote the topmost resolution for the DNS zone for various types of records. They can also include reserved names such as ‘asuid’ for TXT records that have hash values from the app service so that the record can be located by suffixing asuid with the domain name. Even though this record might exist, the validation might fail stating that a record for such asuid.domain.com was not found.

Before falling back to the default naming convention that avoids the use of custom domains, there are some mitigations to try. For example, we could add a TXT record for ‘awverify’ reserved name that points to the default name of the app service. Another correction might involve making sure the ‘asuid’ is not suffixed with any other name parts when specifying the TXT record with the hash value of the app service.  Getting a DIG report generated by a DNS lookup tool from Google might also help with transparency to the resolution. Finally, DNS names can take anywhere from one hour to 48 hours to propagate.

Thursday, June 15, 2023

 

How to address IaC shortcomings – Part 4?

A previous article discussed a resolution to IaC shortcomings for declaring resources with configuration not yet supported by an IaC repository. This article continues that discussion with native support for extensibility with Terraform.

As a recap, IaC providers enable templates and blueprints so that they fit nicely into a CI/CD and provide a declarative framework that can be applied idempotently providing robustness against transient and intermittent failures. Terraform also has features such that it tracks the state of the real-world resources which makes Day-2 and onward operations easier and more powerful. With Azure Blueprints, the relationship between what should be deployed and what was deployed is preserved. This connection supports improved tracking and auditing of deployments. It even works across several subscriptions with the same blueprint.

The organization can make use of the best of both worlds with a folder structure that separates the Terraform templates into a folder called ‘module’ and the ARM Templates in another folder at the same level and named something like ‘subscription-deployments’ and includes native blueprints and templates. The GitHub workflow definitions will leverage proper handling of either location or trigger the workflow on any changes to either of these locations.

The native support for extensibility depends on naming and logic.

Naming is facilitated with canned prefixes/suffixes and dynamic random string to make each rollout independent of the previous. Some examples include:

resource "random_string" "unique" {

  count   = var.enable_static_website && var.enable_cdn_profile ? 1 : 0

  length  = 8

  special = false

  upper   = false

}

 

Logic can be written out with PowerShell for Azure public cloud which is the de facto standard for automation language. Then a pseudo resource can be added using this logic as follows:

resource "null_resource" "add_custom_domain" {

  count = var.custom_domain_name != null ? 1 : 0

  triggers = { always_run = timestamp() }

  depends_on = [

    azurerm_app_service.web-app

  ]

 

  provisioner "local-exec" {

    command = "pwsh ${path.module}/Setup-AzCdnCustomDomain.ps1"

    environment = {

      CUSTOM_DOMAIN      = var.custom_domain_name

      RG_NAME            = var.resource_group_name

      FRIENDLY_NAME      = var.friendly_name

      STATIC_CDN_PROFILE = var.cdn_profile_name

    }

  }

}

 

PowerShell scripts can help with both the deployment as well as the pipeline automations. There are a few caveats with scripts because the general preference is for declarative and idempotent IaC rather than script so extensibility must be given the same due consideration as customization.

All scripts can be stored in folders with names ending with ‘scripts’.
 These are sufficient to address the above-mentioned shortcomings in the Infrastructure-as-Code.